Path: blob/main/crates/wizer/tests/all/component.rs
3068 views
use wasmtime::component::{Component, Instance, Linker, Val};1use wasmtime::{Engine, Result, Store, ToWasmtimeResult as _, bail, error::Context as _};2use wasmtime_wizer::Wizer;34fn fail_wizening(msg: &str, wasm: &[u8]) -> Result<()> {5let _ = env_logger::try_init();67let wasm = wat::parse_bytes(wasm)?;8log::debug!(9"testing wizening failure for wasm:\n{}",10wasmprinter::print_bytes(&wasm).to_wasmtime_result()?11);12match Wizer::new().instrument_component(&wasm) {13Ok(_) => bail!("expected wizening to fail"),14Err(e) => {15let err = format!("{e}");16if !err.contains(msg) {17bail!("unexpected error: {err}");18}19Ok(())20}21}22}2324#[test]25fn unsupported_constructs() -> Result<()> {26fail_wizening(27"does not currently support component imports",28br#"(component29(import "x" (component))30)"#,31)?;3233fail_wizening(34"nested components with modules not currently supported",35br#"(component36(component (core module))37)"#,38)?;39fail_wizening(40"nested components with modules not currently supported",41br#"(component42(component)43(component (core module))44)"#,45)?;46fail_wizening(47"wizer does not currently support module imports",48br#"(component49(component (import "x" (core module)))50)"#,51)?;52fail_wizening(53"wizer does not currently support module aliases",54br#"(component55(core module $a)56(component57(core instance (instantiate $a))58)59)"#,60)?;61fail_wizening(62"wizer does not currently support component aliases",63br#"(component64(component $a)65(component66(instance (instantiate $a))67)68)"#,69)?;7071fail_wizening(72"does not currently support component aliases",73br#"(component74(import "x" (instance $i (export "x" (component))))75(alias export $i "x" (component $c))76)"#,77)?;7879fail_wizening(80"does not currently support module imports",81br#"(component82(import "x" (core module))83)"#,84)?;8586fail_wizening(87"does not currently support module exports",88br#"(component89(core module $x)90(export "x" (core module $x))91)"#,92)?;9394fail_wizening(95"does not currently support module aliases",96br#"(component97(import "x" (instance $i (export "x" (core module))))98(alias export $i "x" (core module $c))99)"#,100)?;101fail_wizening(102"does not currently support component start functions",103br#"(component104(import "f" (func $f))105(start $f)106)"#,107)?;108109fail_wizening(110"modules may be instantiated at most once",111br#"(component112(core module $a)113(core instance $a1 (instantiate $a))114(core instance $a2 (instantiate $a))115)"#,116)?;117118Ok(())119}120121fn store() -> Result<Store<()>> {122let engine = Engine::default();123Ok(Store::new(&engine, ()))124}125126async fn instantiate(store: &mut Store<()>, component: &Component) -> Result<Instance> {127let mut linker = Linker::new(store.engine());128linker.define_unknown_imports_as_traps(component)?;129linker.instantiate_async(store, component).await130}131132async fn wizen(wat: &str) -> Result<Vec<u8>> {133let _ = env_logger::try_init();134let wasm = wat::parse_str(wat)?;135136log::debug!(137"=== PreWizened Wasm ==========================================================\n\138{}\n\139===========================================================================",140wasmprinter::print_bytes(&wasm).unwrap()141);142let mut store = store()?;143let wasm = Wizer::new()144.run_component(&mut store, &wasm, instantiate)145.await?;146log::debug!(147"=== Wizened Wasm ==========================================================\n\148{}\n\149===========================================================================",150wasmprinter::print_bytes(&wasm).unwrap()151);152if log::log_enabled!(log::Level::Debug) {153std::fs::write("test.wasm", &wasm).unwrap();154}155156Ok(wasm)157}158159async fn wizen_and_run_wasm(expected: u32, wat: &str) -> Result<()> {160let wasm = wizen(wat).await?;161162let mut store = store()?;163let module =164Component::new(store.engine(), wasm).context("Wasm test case failed to compile")?;165166let linker = Linker::new(store.engine());167let instance = linker.instantiate_async(&mut store, &module).await?;168169let run = instance.get_func(&mut store, "run").ok_or_else(|| {170wasmtime::format_err!("the test Wasm component does not export a `run` function")171})?;172173let mut actual = [Val::U8(0)];174run.call_async(&mut store, &[], &mut actual).await?;175let actual = match actual[0] {176Val::U32(x) => x,177_ => wasmtime::bail!("expected an u32 result"),178};179wasmtime::ensure!(180expected == actual,181"expected `{expected}`, found `{actual}`",182);183184Ok(())185}186187#[tokio::test]188async fn simple() -> Result<()> {189wizen_and_run_wasm(19042,191r#"(component192(core module $m193(func (export "init"))194195(func (export "run") (result i32)196i32.const 42197)198)199(core instance $i (instantiate $m))200(func (export "run") (result u32) (canon lift (core func $i "run")))201(func (export "wizer-initialize") (canon lift (core func $i "init")))202)"#,203)204.await?;205206Ok(())207}208209#[tokio::test]210async fn snapshot_global_i32() -> Result<()> {211wizen_and_run_wasm(2121,213r#"(component214(core module $m215(global $g (mut i32) i32.const 0)216(func (export "init") (global.set $g (i32.const 1)))217(func (export "run") (result i32) global.get $g)218)219(core instance $i (instantiate $m))220(func (export "run") (result u32) (canon lift (core func $i "run")))221(func (export "wizer-initialize") (canon lift (core func $i "init")))222)"#,223)224.await?;225226Ok(())227}228229#[tokio::test]230async fn snapshot_global_i64() -> Result<()> {231wizen_and_run_wasm(2321,233r#"(component234(core module $m235(global $g (mut i64) i64.const 0)236(func (export "init") (global.set $g (i64.const 1)))237(func (export "run") (result i32)238global.get $g239i32.wrap_i64240)241)242(core instance $i (instantiate $m))243(func (export "run") (result u32) (canon lift (core func $i "run")))244(func (export "wizer-initialize") (canon lift (core func $i "init")))245)"#,246)247.await?;248249Ok(())250}251252#[tokio::test]253async fn snapshot_global_f32() -> Result<()> {254wizen_and_run_wasm(2551,256r#"(component257(core module $m258(global $g (mut f32) f32.const 0)259(func (export "init") (global.set $g (f32.const 1)))260(func (export "run") (result i32)261global.get $g262i32.trunc_f32_s)263)264(core instance $i (instantiate $m))265(func (export "run") (result u32) (canon lift (core func $i "run")))266(func (export "wizer-initialize") (canon lift (core func $i "init")))267)"#,268)269.await?;270271Ok(())272}273274#[tokio::test]275async fn snapshot_global_f64() -> Result<()> {276wizen_and_run_wasm(2771,278r#"(component279(core module $m280(global $g (mut f64) f64.const 0)281(func (export "init") (global.set $g (f64.const 1)))282(func (export "run") (result i32)283global.get $g284i32.trunc_f64_s)285)286(core instance $i (instantiate $m))287(func (export "run") (result u32) (canon lift (core func $i "run")))288(func (export "wizer-initialize") (canon lift (core func $i "init")))289)"#,290)291.await?;292293Ok(())294}295296#[test]297fn v128_globals() -> Result<()> {298fail_wizening(299"component wizening does not support v128 globals",300br#"(component301(core module $a302(global (export "x") (mut v128) (v128.const i32x4 1 2 3 4))303)304(core instance (instantiate $a))305)"#,306)307}308309#[tokio::test]310async fn snapshot_memory() -> Result<()> {311wizen_and_run_wasm(312201,313r#"(component314(core module $m315(memory 1)316(func (export "init")317i32.const 200318i32.const 100319i32.store320i32.const 300321i32.const 101322i32.store323)324(func (export "run") (result i32)325i32.const 200326i32.load327i32.const 300328i32.load329i32.add330)331)332(core instance $i (instantiate $m))333(func (export "run") (result u32) (canon lift (core func $i "run")))334(func (export "wizer-initialize") (canon lift (core func $i "init")))335)"#,336)337.await?;338339Ok(())340}341342#[tokio::test]343async fn nested_components() -> Result<()> {344wizen_and_run_wasm(34542,346r#"(component347(component $a)348(instance (instantiate $a))349(instance (export "hi") (instantiate $a))350351(component $b352(type $t string)353(import "x" (type (eq $t)))354(component $a)355(instance (instantiate $a))356(instance (export "hi") (instantiate $a))357)358(type $x string)359(instance (instantiate $b360(with "x" (type $x))361))362(instance (export "hi2") (instantiate $b363(with "x" (type $x))364))365366(core module $m367(func (export "init"))368(func (export "run") (result i32) i32.const 42)369)370(core instance $i (instantiate $m))371(func (export "run") (result u32) (canon lift (core func $i "run")))372(func (export "wizer-initialize") (canon lift (core func $i "init")))373)"#,374)375.await?;376377Ok(())378}379380#[tokio::test]381async fn multiple_modules() -> Result<()> {382wizen_and_run_wasm(383100 + 101 + 200 + 201 + 7 + 112,384r#"(component385(core module $a386(memory 1)387(global $g (export "g") (mut i32) (i32.const 0))388389(func (export "init")390i32.const 200391i32.const 100392i32.store393i32.const 300394i32.const 101395i32.store396)397398(func (export "run") (result i32)399i32.const 200400i32.load401i32.const 300402i32.load403i32.add404global.get $g405i32.add406)407)408(core instance $a (instantiate $a))409410(core module $b411(import "a" "g" (global $g (mut i32)))412(import "a" "init" (func $init))413(import "a" "run" (func $run (result i32)))414(memory (export "mem") 1)415(func (export "init")416call $init417i32.const 400418i32.const 200419i32.store420i32.const 500421i32.const 201422i32.store423424i32.const 111425global.set $g426)427(func (export "run") (result i32)428i32.const 400429i32.load430i32.const 500431i32.load432i32.add433call $run434i32.add435)436)437(core instance $b (instantiate $b (with "a" (instance $a))))438439(core module $c440(import "a" "g" (global $g (mut i32)))441(import "b" "init" (func $init))442(import "b" "run" (func $run (result i32)))443(import "b" "mem" (memory 1))444445(func (export "init")446call $init447448i32.const 1449memory.grow450i32.const -1451i32.eq452if unreachable end453454i32.const 65536455i32.const 7456i32.store457458;; overwrite a#init with a different value, make sure this459;; one is snapshot460i32.const 112461global.set $g462)463(func (export "run") (result i32)464i32.const 65536465i32.load466call $run467i32.add468)469)470(core instance $c (instantiate $c471(with "a" (instance $a))472(with "b" (instance $b))473))474475(func (export "run") (result u32) (canon lift (core func $c "run")))476(func (export "wizer-initialize") (canon lift (core func $c "init")))477)"#,478)479.await?;480481Ok(())482}483484#[tokio::test]485async fn export_is_removed() -> Result<()> {486let wasm = wizen(487r#"(component488(core module $a489(func (export "init"))490)491(core instance $a (instantiate $a))492(func $a (canon lift (core func $a "init")))493(export "wizer-initialize" (func $a))494)"#,495)496.await?;497498let names = exports(&wasm);499assert!(names.is_empty());500501let wasm = wizen(502r#"(component503(core module $a504(func (export "init"))505)506(core instance $a (instantiate $a))507(func $a (canon lift (core func $a "init")))508(export "other" (func $a))509(export "wizer-initialize" (func $a))510)"#,511)512.await?;513let names = exports(&wasm);514assert_eq!(names, ["other"]);515516let wasm = wizen(517r#"(component518(core module $a519(func (export "init"))520)521(core instance $a (instantiate $a))522(func $a (canon lift (core func $a "init")))523(export "other1" (func $a))524(export "wizer-initialize" (func $a))525(export "other2" (func $a))526)"#,527)528.await?;529let names = exports(&wasm);530assert_eq!(names, ["other1", "other2"]);531532let wasm = wizen(533r#"(component534(core module $a535(func (export "init"))536)537(core instance $a (instantiate $a))538(func $a (canon lift (core func $a "init")))539(export "other1" (func $a))540(export "other2" (func $a))541(export "wizer-initialize" (func $a))542)"#,543)544.await?;545let names = exports(&wasm);546assert_eq!(names, ["other1", "other2"]);547548let wasm = wizen(549r#"(component550(core module $a551(func (export "init"))552)553(core instance $a (instantiate $a))554(func $a (canon lift (core func $a "init")))555(export "wizer-initialize" (func $a))556(export "other1" (func $a))557(export "other2" (func $a))558)"#,559)560.await?;561let names = exports(&wasm);562assert_eq!(names, ["other1", "other2"]);563564let wasm = wizen(565r#"(component566(core module $a567(func (export "init"))568)569(core instance $a (instantiate $a))570(func $a (canon lift (core func $a "init")))571(export $x "other1" (func $a))572(export "wizer-initialize" (func $a))573(export "other2" (func $x))574)"#,575)576.await?;577let names = exports(&wasm);578assert_eq!(names, ["other1", "other2"]);579580let wasm = wizen(581r#"(component582(import "x" (func))583(core module $a584(func (export "init"))585)586(core instance $a (instantiate $a))587(func $a (canon lift (core func $a "init")))588(export $x "other1" (func $a))589(export "wizer-initialize" (func $a))590(export "other2" (func $x))591)"#,592)593.await?;594let names = exports(&wasm);595assert_eq!(names, ["other1", "other2"]);596597return Ok(());598599fn exports(wasm: &[u8]) -> Vec<&str> {600wasmparser::Parser::new(0)601.parse_all(&wasm)602.filter_map(|r| r.ok())603.filter_map(|payload| match payload {604wasmparser::Payload::ComponentExportSection(s) => Some(s),605_ => None,606})607.flat_map(|section| section.into_iter().map(|e| e.unwrap().name.0))608.collect()609}610}611612613