use anyhow::Result;
use wasmtime::component::types::ComponentItem;
use wasmtime::component::{Component, Linker, Type};
use wasmtime::{Module, Precompiled, Store};
#[test]
fn module_component_mismatch() -> Result<()> {
let engine = super::engine();
let module = Module::new(&engine, "(module)")?.serialize()?;
let component = Component::new(&engine, "(component)")?.serialize()?;
unsafe {
assert!(Module::deserialize(&engine, &component).is_err());
assert!(Component::deserialize(&engine, &module).is_err());
}
Ok(())
}
#[test]
fn bare_bones() -> Result<()> {
let engine = super::engine();
let component = Component::new(&engine, "(component)")?.serialize()?;
assert_eq!(component, engine.precompile_component(b"(component)")?);
let component = unsafe { Component::deserialize(&engine, &component)? };
let mut store = Store::new(&engine, ());
Linker::new(&engine).instantiate(&mut store, &component)?;
Ok(())
}
#[test]
#[cfg_attr(miri, ignore)]
fn mildly_more_interesting() -> Result<()> {
let engine = super::engine();
let component = Component::new(
&engine,
r#"
(component
(core module $a
(func (export "a") (result i32)
i32.const 100)
)
(core instance $a (instantiate $a))
(core module $b
(import "a" "a" (func $import (result i32)))
(func (export "a") (result i32)
call $import
i32.const 3
i32.add)
)
(core instance $b (instantiate $b (with "a" (instance $a))))
(func (export "a") (result u32)
(canon lift (core func $b "a"))
)
)
"#,
)?
.serialize()?;
let component = unsafe { Component::deserialize(&engine, &component)? };
let mut store = Store::new(&engine, ());
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let func = instance.get_typed_func::<(), (u32,)>(&mut store, "a")?;
assert_eq!(func.call(&mut store, ())?, (103,));
Ok(())
}
#[test]
fn deserialize_from_serialized() -> Result<()> {
let engine = super::engine();
let buffer1 = Component::new(&engine, "(component (core module))")?.serialize()?;
let buffer2 = unsafe { Component::deserialize(&engine, &buffer1)?.serialize()? };
assert!(buffer1 == buffer2);
Ok(())
}
#[test]
fn cannot_serialize_exported_module() -> Result<()> {
let engine = super::engine();
let component = Component::new(
&engine,
r#"(component
(core module $m)
(export "a" (core module $m))
)"#,
)?;
let mut store = Store::new(&engine, ());
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let module = instance.get_module(&mut store, "a").unwrap();
assert!(module.serialize().is_err());
Ok(())
}
#[test]
fn usable_exported_modules() -> Result<()> {
let engine = super::engine();
let component = Component::new(
&engine,
r#"(component
(core module $m)
(core module $m1 (export "a")
(import "" "" (func (param i32)))
)
)"#,
)?;
let mut store = Store::new(&engine, ());
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
let module = instance.get_module(&mut store, "a").unwrap();
let mut core_linker = wasmtime::Linker::new(&engine);
core_linker.func_wrap("", "", |_: u32| {})?;
core_linker.instantiate(&mut store, &module)?;
Ok(())
}
#[test]
#[cfg_attr(miri, ignore)]
fn detect_precompiled() -> Result<()> {
let engine = super::engine();
let buffer = Component::new(&engine, "(component)")?.serialize()?;
assert_eq!(engine.detect_precompiled(&[]), None);
assert_eq!(engine.detect_precompiled(&buffer[..5]), None);
assert_eq!(
engine.detect_precompiled(&buffer),
Some(Precompiled::Component)
);
Ok(())
}
#[test]
fn reflect_resource_import() -> Result<()> {
let engine = super::engine();
let c = Component::new(
&engine,
r#"
(component
(import "x" (type $x (sub resource)))
(import "y" (func (result (own $x))))
)
"#,
)?;
let ty = c.component_type();
let mut imports = ty.imports(&engine);
let (_, x) = imports.next().unwrap();
let (_, y) = imports.next().unwrap();
let x = match x {
ComponentItem::Resource(t) => t,
_ => unreachable!(),
};
let y = match y {
ComponentItem::ComponentFunc(t) => t,
_ => unreachable!(),
};
let result = y.results().next().unwrap();
assert_eq!(result, Type::Own(x));
Ok(())
}
#[test]
#[cfg_attr(miri, ignore)]
fn truncated_component_binaries_dont_panic() -> Result<()> {
let engine = super::engine();
let binary = wat::parse_str(
r#"
(component
(import "a" (core module $m0
(import "" "" (func))
))
(core module $m1
(func (export ""))
)
(core instance $i1 (instantiate (module $m1)))
(func $f (canon lift (core func $i1 "f")))
(component $c1
(import "f" (func))
(core module $m2
(func (export "g"))
)
(core instance $i2 (instantiate $m2))
(func (export "g")
(canon lift (core func $i2 "g"))
)
)
(instance $i3 (instantiate $c1 (with "f" (func $f))))
(func (export "g") (alias export $i3 "g"))
)
"#,
)?;
for i in 1..binary.len() - 1 {
let _ = Component::from_binary(&engine, &binary[0..i]);
}
Ok(())
}