Path: blob/main/tests/all/component_model/dynamic.rs
1691 views
#![cfg(not(miri))]12use super::{Param, Type, make_echo_component, make_echo_component_with_params};3use anyhow::Result;4use wasmtime::component::types::{self, Case, ComponentItem, Field};5use wasmtime::component::{Component, Linker, ResourceType, Val};6use wasmtime::{Module, Store};7use wasmtime_component_util::REALLOC_AND_FREE;8use wasmtime_test_util::component::FuncExt;910#[test]11fn primitives() -> Result<()> {12let engine = super::engine();13let mut store = Store::new(&engine, ());14let mut output = [Val::Bool(false)];1516for (input, ty, param) in [17(Val::Bool(true), "bool", Param(Type::U8, Some(0))),18(Val::S8(-42), "s8", Param(Type::S8, Some(0))),19(Val::U8(42), "u8", Param(Type::U8, Some(0))),20(Val::S16(-4242), "s16", Param(Type::S16, Some(0))),21(Val::U16(4242), "u16", Param(Type::U16, Some(0))),22(Val::S32(-314159265), "s32", Param(Type::I32, Some(0))),23(Val::U32(314159265), "u32", Param(Type::I32, Some(0))),24(Val::S64(-31415926535897), "s64", Param(Type::I64, Some(0))),25(Val::U64(31415926535897), "u64", Param(Type::I64, Some(0))),26(27Val::Float32(3.14159265),28"float32",29Param(Type::F32, Some(0)),30),31(32Val::Float64(3.14159265),33"float64",34Param(Type::F64, Some(0)),35),36(Val::Char('��'), "char", Param(Type::I32, Some(0))),37] {38let component = Component::new(&engine, make_echo_component_with_params(ty, &[param]))?;39let instance = Linker::new(&engine).instantiate(&mut store, &component)?;40let func = instance.get_func(&mut store, "echo").unwrap();41func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;4243assert_eq!(input, output[0]);44}4546// Sad path: type mismatch4748let component = Component::new(49&engine,50make_echo_component_with_params("float64", &[Param(Type::F64, Some(0))]),51)?;52let instance = Linker::new(&engine).instantiate(&mut store, &component)?;53let func = instance.get_func(&mut store, "echo").unwrap();54let err = func55.call_and_post_return(&mut store, &[Val::U64(42)], &mut output)56.unwrap_err();5758assert!(err.to_string().contains("type mismatch"), "{err}");5960// Sad path: arity mismatch (too many)6162let err = func63.call_and_post_return(64&mut store,65&[Val::Float64(3.14159265), Val::Float64(3.14159265)],66&mut output,67)68.unwrap_err();6970assert!(71err.to_string().contains("expected 1 argument(s), got 2"),72"{err}"73);7475// Sad path: arity mismatch (too few)7677let err = func78.call_and_post_return(&mut store, &[], &mut output)79.unwrap_err();80assert!(81err.to_string().contains("expected 1 argument(s), got 0"),82"{err}"83);8485let err = func86.call_and_post_return(&mut store, &output, &mut [])87.unwrap_err();88assert!(89err.to_string().contains("expected 1 result(s), got 0"),90"{err}"91);9293Ok(())94}9596#[test]97fn strings() -> Result<()> {98let engine = super::engine();99let mut store = Store::new(&engine, ());100101let component = Component::new(&engine, make_echo_component("string", 8))?;102let instance = Linker::new(&engine).instantiate(&mut store, &component)?;103let func = instance.get_func(&mut store, "echo").unwrap();104let input = Val::String("hello, component!".into());105let mut output = [Val::Bool(false)];106func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;107assert_eq!(input, output[0]);108109Ok(())110}111112#[test]113fn lists() -> Result<()> {114let engine = super::engine();115let mut store = Store::new(&engine, ());116117let component = Component::new(&engine, make_echo_component("(list u32)", 8))?;118let instance = Linker::new(&engine).instantiate(&mut store, &component)?;119let func = instance.get_func(&mut store, "echo").unwrap();120let input = Val::List(vec![121Val::U32(32343),122Val::U32(79023439),123Val::U32(2084037802),124]);125let mut output = [Val::Bool(false)];126func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;127128assert_eq!(input, output[0]);129130// Sad path: type mismatch131132let err = Val::List(vec![133Val::U32(32343),134Val::U32(79023439),135Val::Float32(3.14159265),136]);137let err = func138.call_and_post_return(&mut store, &[err], &mut output)139.unwrap_err();140assert!(err.to_string().contains("type mismatch"), "{err}");141142Ok(())143}144145#[test]146fn records() -> Result<()> {147let engine = super::engine();148let mut store = Store::new(&engine, ());149150let component = Component::new(151&engine,152make_echo_component_with_params(153r#"154(type $c' (record155(field "D" bool)156(field "E" u32)157))158(export $c "c" (type $c'))159(type $Foo' (record160(field "A" u32)161(field "B" float64)162(field "C" $c)163))164"#,165&[166Param(Type::I32, Some(0)),167Param(Type::F64, Some(8)),168Param(Type::U8, Some(16)),169Param(Type::I32, Some(20)),170],171),172)?;173let instance = Linker::new(&engine).instantiate(&mut store, &component)?;174let func = instance.get_func(&mut store, "echo").unwrap();175let input = Val::Record(vec![176("A".into(), Val::U32(32343)),177("B".into(), Val::Float64(3.14159265)),178(179"C".into(),180Val::Record(vec![181("D".into(), Val::Bool(false)),182("E".into(), Val::U32(2084037802)),183]),184),185]);186let mut output = [Val::Bool(false)];187func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;188189assert_eq!(input, output[0]);190191// Sad path: type mismatch192193let err = Val::Record(vec![194("A".into(), Val::S32(32343)),195("B".into(), Val::Float64(3.14159265)),196(197"C".into(),198Val::Record(vec![199("D".into(), Val::Bool(false)),200("E".into(), Val::U32(2084037802)),201]),202),203]);204let instance = Linker::new(&engine).instantiate(&mut store, &component)?;205let func = instance.get_func(&mut store, "echo").unwrap();206let err = func207.call_and_post_return(&mut store, &[err], &mut output)208.unwrap_err();209assert!(err.to_string().contains("type mismatch"), "{err}");210211// Sad path: too many fields212213let err = Val::Record(vec![214("A".into(), Val::U32(32343)),215("B".into(), Val::Float64(3.14159265)),216(217"C".into(),218Val::Record(vec![219("D".into(), Val::Bool(false)),220("E".into(), Val::U32(2084037802)),221]),222),223("F".into(), Val::Bool(true)),224]);225let instance = Linker::new(&engine).instantiate(&mut store, &component)?;226let func = instance.get_func(&mut store, "echo").unwrap();227let err = func228.call_and_post_return(&mut store, &[err], &mut output)229.unwrap_err();230assert!(231err.to_string().contains("expected 3 fields, got 4"),232"{err}"233);234235// Sad path: too few fields236237let err = Val::Record(vec![238("A".into(), Val::U32(32343)),239("B".into(), Val::Float64(3.14159265)),240]);241let instance = Linker::new(&engine).instantiate(&mut store, &component)?;242let func = instance.get_func(&mut store, "echo").unwrap();243let err = func244.call_and_post_return(&mut store, &[err], &mut output)245.unwrap_err();246assert!(247err.to_string().contains("expected 3 fields, got 2"),248"{err}"249);250251Ok(())252}253254#[test]255fn variants() -> Result<()> {256let engine = super::engine();257let mut store = Store::new(&engine, ());258259let fragment = r#"260(type $c' (record (field "D" bool) (field "E" u32)))261(export $c "c" (type $c'))262(type $Foo' (variant263(case "A" u32)264(case "B" float64)265(case "C" $c)266))267"#;268269let component = Component::new(270&engine,271make_echo_component_with_params(272fragment,273&[274Param(Type::U8, Some(0)),275Param(Type::I64, Some(8)),276Param(Type::I32, None),277],278),279)?;280let instance = Linker::new(&engine).instantiate(&mut store, &component)?;281let func = instance.get_func(&mut store, "echo").unwrap();282let input = Val::Variant("B".into(), Some(Box::new(Val::Float64(3.14159265))));283let mut output = [Val::Bool(false)];284func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;285286assert_eq!(input, output[0]);287288// Do it again, this time using case "C"289290let component = Component::new(291&engine,292make_echo_component_with_params(293fragment,294&[295Param(Type::U8, Some(0)),296Param(Type::I64, Some(8)),297Param(Type::I32, Some(12)),298],299),300)?;301let instance = Linker::new(&engine).instantiate(&mut store, &component)?;302let func = instance.get_func(&mut store, "echo").unwrap();303let input = Val::Variant(304"C".into(),305Some(Box::new(Val::Record(vec![306("D".into(), Val::Bool(true)),307("E".into(), Val::U32(314159265)),308]))),309);310func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;311312assert_eq!(input, output[0]);313314// Sad path: type mismatch315316let instance = Linker::new(&engine).instantiate(&mut store, &component)?;317let func = instance.get_func(&mut store, "echo").unwrap();318let err = Val::Variant("B".into(), Some(Box::new(Val::U64(314159265))));319let err = func320.call_and_post_return(&mut store, &[err], &mut output)321.unwrap_err();322assert!(err.to_string().contains("type mismatch"), "{err}");323324let instance = Linker::new(&engine).instantiate(&mut store, &component)?;325let func = instance.get_func(&mut store, "echo").unwrap();326let err = Val::Variant("B".into(), None);327let err = func328.call_and_post_return(&mut store, &[err], &mut output)329.unwrap_err();330assert!(331err.to_string().contains("expected a payload for case `B`"),332"{err}"333);334335// Sad path: unknown case336337let instance = Linker::new(&engine).instantiate(&mut store, &component)?;338let func = instance.get_func(&mut store, "echo").unwrap();339let err = Val::Variant("D".into(), Some(Box::new(Val::U64(314159265))));340let err = func341.call_and_post_return(&mut store, &[err], &mut output)342.unwrap_err();343assert!(err.to_string().contains("unknown variant case"), "{err}");344345let instance = Linker::new(&engine).instantiate(&mut store, &component)?;346let func = instance.get_func(&mut store, "echo").unwrap();347let err = Val::Variant("D".into(), None);348let err = func349.call_and_post_return(&mut store, &[err], &mut output)350.unwrap_err();351assert!(err.to_string().contains("unknown variant case"), "{err}");352353// Make sure we lift variants which have cases of different sizes with the correct alignment354355let component = Component::new(356&engine,357make_echo_component_with_params(358r#"359(type $c' (record (field "D" bool) (field "E" u32)))360(export $c "c" (type $c'))361(type $a' (variant362(case "A" u32)363(case "B" float64)364(case "C" $c)365))366(export $a "a" (type $a'))367(type $Foo' (record368(field "A" $a)369(field "B" u32)370))371"#,372&[373Param(Type::U8, Some(0)),374Param(Type::I64, Some(8)),375Param(Type::I32, None),376Param(Type::I32, Some(16)),377],378),379)?;380let instance = Linker::new(&engine).instantiate(&mut store, &component)?;381let func = instance.get_func(&mut store, "echo").unwrap();382let input = Val::Record(vec![383(384"A".into(),385Val::Variant("A".into(), Some(Box::new(Val::U32(314159265)))),386),387("B".into(), Val::U32(628318530)),388]);389func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;390391assert_eq!(input, output[0]);392393Ok(())394}395396#[test]397fn flags() -> Result<()> {398let engine = super::engine();399let mut store = Store::new(&engine, ());400401let component = Component::new(402&engine,403make_echo_component_with_params(404r#"(flags "A" "B" "C" "D" "E")"#,405&[Param(Type::U8, Some(0))],406),407)?;408let instance = Linker::new(&engine).instantiate(&mut store, &component)?;409let func = instance.get_func(&mut store, "echo").unwrap();410let input = Val::Flags(vec!["B".into(), "D".into()]);411let mut output = [Val::Bool(false)];412func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;413414assert_eq!(input, output[0]);415416// Sad path: unknown flags417418let err = Val::Flags(vec!["B".into(), "D".into(), "F".into()]);419let err = func420.call_and_post_return(&mut store, &[err], &mut output)421.unwrap_err();422assert!(err.to_string().contains("unknown flag"), "{err}");423424Ok(())425}426427#[test]428fn everything() -> Result<()> {429// This serves to test both nested types and storing parameters on the heap (i.e. exceeding `MAX_STACK_PARAMS`)430431let engine = super::engine();432let mut store = Store::new(&engine, ());433434let component = Component::new(435&engine,436make_echo_component_with_params(437r#"438(type $b' (enum "a" "b"))439(export $b "b" (type $b'))440(type $c' (record (field "D" bool) (field "E" u32)))441(export $c "c" (type $c'))442(type $f' (flags "G" "H" "I"))443(export $f "f" (type $f'))444(type $m' (record (field "N" bool) (field "O" u32)))445(export $m "m" (type $m'))446(type $j' (variant447(case "K" u32)448(case "L" float64)449(case "M" $m)450))451(export $j "j" (type $j'))452453(type $Foo' (record454(field "A" u32)455(field "B" $b)456(field "C" $c)457(field "F" (list $f))458(field "J" $j)459(field "P" s8)460(field "Q" s16)461(field "R" s32)462(field "S" s64)463(field "T" float32)464(field "U" float64)465(field "V" string)466(field "W" char)467(field "Y" (tuple u32 u32))468(field "AA" (option u32))469(field "BB" (result string (error string)))470))471"#,472&[473Param(Type::I32, Some(0)),474Param(Type::U8, Some(4)),475Param(Type::U8, Some(5)),476Param(Type::I32, Some(8)),477Param(Type::I32, Some(12)),478Param(Type::I32, Some(16)),479Param(Type::U8, Some(20)),480Param(Type::I64, Some(28)),481Param(Type::I32, Some(32)),482Param(Type::S8, Some(36)),483Param(Type::S16, Some(38)),484Param(Type::I32, Some(40)),485Param(Type::I64, Some(48)),486Param(Type::F32, Some(56)),487Param(Type::F64, Some(64)),488Param(Type::I32, Some(72)),489Param(Type::I32, Some(76)),490Param(Type::I32, Some(80)),491Param(Type::I32, Some(84)),492Param(Type::I32, Some(88)),493Param(Type::I64, Some(96)),494Param(Type::U8, Some(104)),495Param(Type::I32, Some(108)),496Param(Type::U8, Some(112)),497Param(Type::I32, Some(116)),498Param(Type::I32, Some(120)),499],500),501)?;502let instance = Linker::new(&engine).instantiate(&mut store, &component)?;503let func = instance.get_func(&mut store, "echo").unwrap();504let input = Val::Record(vec![505("A".into(), Val::U32(32343)),506("B".into(), Val::Enum("b".to_string())),507(508"C".into(),509Val::Record(vec![510("D".to_string(), Val::Bool(false)),511("E".to_string(), Val::U32(2084037802)),512]),513),514(515"F".into(),516Val::List(vec![Val::Flags(vec!["G".to_string(), "I".to_string()])]),517),518(519"J".into(),520Val::Variant("L".to_string(), Some(Box::new(Val::Float64(3.14159265)))),521),522("P".into(), Val::S8(42)),523("Q".into(), Val::S16(4242)),524("R".into(), Val::S32(42424242)),525("S".into(), Val::S64(424242424242424242)),526("T".into(), Val::Float32(3.14159265)),527("U".into(), Val::Float64(3.14159265)),528("V".into(), Val::String("wow, nice types".to_string())),529("W".into(), Val::Char('��')),530("Y".into(), Val::Tuple(vec![Val::U32(42), Val::U32(24)])),531(532"AA".into(),533Val::Option(Some(Box::new(Val::U32(314159265)))),534),535(536"BB".into(),537Val::Result(Ok(Some(Box::new(Val::String("no problem".to_string()))))),538),539]);540let mut output = [Val::Bool(false)];541func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;542543assert_eq!(input, output[0]);544545Ok(())546}547548#[test]549fn introspection() -> Result<()> {550let engine = super::engine();551552let component = Component::new(553&engine,554format!(555r#"556(component557(import "res" (type $res (sub resource)))558559(import "ai" (instance $i))560(import "bi" (instance $i2 (export "m" (core module))))561562(alias export $i2 "m" (core module $m))563564(type $t (func (param "a" u32) (result u32)))565(component $a566(core module $m567(func (export "add-five") (param i32) (result i32)568local.get 0569i32.const 5570i32.add)571)572(core instance $m (instantiate $m))573(func (export "add-five") (type $t) (canon lift (core func $m "add-five")))574)575(component $b576(import "interface-v1" (instance $i577(export "add-five" (func (type $t)))))578(core module $m579(func $add-five (import "interface-0.1.0" "add-five") (param i32) (result i32))580(func) ;; causes index out of bounds581(func (export "run") (result i32) i32.const 0 call $add-five)582)583(core func $add-five (canon lower (func $i "add-five")))584(core instance $i (instantiate 0585(with "interface-0.1.0" (instance586(export "add-five" (func $add-five))587))588))589(func (result u32) (canon lift (core func $i "run")))590(export "run" (func 1))591)592(instance $a (instantiate $a))593(instance $b (instantiate $b (with "interface-v1" (instance $a))))594(export "run" (func $b "run"))595596(component $c597(component $c598(export "m" (core module $m))599)600(instance $c (instantiate $c))601(export "i" (instance $c))602)603(instance $c (instantiate $c))604(export "i" (instance $c))605(export "r" (instance $i))606(export "r2" (instance $i2))607608(type $b' (enum "a" "b"))609(export $b "b" (type $b'))610(type $c' (record (field "D" bool) (field "E" u32)))611(export $c "c" (type $c'))612(type $f' (flags "G" "H" "I"))613(export $f "f" (type $f'))614(type $m' (record (field "N" bool) (field "O" u32)))615(export $m "m" (type $m'))616(type $j' (variant617(case "K" u32)618(case "L" float64)619(case "M" $m)620))621(export $j "j" (type $j'))622623(type $Foo' (record624(field "A" u32)625(field "B" $b)626(field "C" $c)627(field "F" (list $f))628(field "J" $j)629(field "P" s8)630(field "Q" s16)631(field "R" s32)632(field "S" s64)633(field "T" float32)634(field "U" float64)635(field "V" string)636(field "W" char)637(field "Y" (tuple u32 u32))638(field "AA" (option u32))639(field "BB" (result string (error string)))640(field "CC" (own $res))641))642(export $Foo "foo" (type $Foo'))643644(core module $m2645(func (export "f") (param i32) (result i32)646local.get 0647)648(memory (export "memory") 1)649{REALLOC_AND_FREE}650)651(core instance $i3 (instantiate $m2))652653(func (export "fn") (param "x" (option $Foo)) (result (option (tuple u32 u32)))654(canon lift655(core func $i3 "f")656(memory $i3 "memory")657(realloc (func $i3 "realloc"))658)659)660)661"#662),663)?;664665struct MyType;666667let mut linker = Linker::<()>::new(&engine);668linker669.root()670.resource("res", ResourceType::host::<MyType>(), |_, _| Ok(()))?;671linker.instance("ai")?;672linker673.instance("bi")?674.module("m", &Module::new(&engine, "(module)")?)?;675676let component_ty = linker.substituted_component_type(&component)?;677678let mut imports = component_ty.imports(linker.engine());679assert_eq!(imports.len(), 3);680let (name, res_ty) = imports.next().unwrap();681assert_eq!(name, "res");682let ComponentItem::Resource(res_ty) = res_ty else {683panic!("`res` import item of wrong type")684};685assert_eq!(res_ty, ResourceType::host::<MyType>());686687let (name, ai_ty) = imports.next().unwrap();688assert_eq!(name, "ai");689let ComponentItem::ComponentInstance(ai_ty) = ai_ty else {690panic!("`ai` import item of wrong type")691};692assert_eq!(ai_ty.exports(linker.engine()).len(), 0);693694let (name, bi_ty) = imports.next().unwrap();695assert_eq!(name, "bi");696let ComponentItem::ComponentInstance(bi_ty) = bi_ty else {697panic!("`bi` import item of wrong type")698};699let mut bi_exports = bi_ty.exports(linker.engine());700assert_eq!(bi_exports.len(), 1);701let (name, bi_m_ty) = bi_exports.next().unwrap();702assert_eq!(name, "m");703let ComponentItem::Module(bi_m_ty) = bi_m_ty else {704panic!("`bi.m` import item of wrong type")705};706assert_eq!(bi_m_ty.imports(linker.engine()).len(), 0);707assert_eq!(bi_m_ty.exports(linker.engine()).len(), 0);708709let mut exports = component_ty.exports(linker.engine());710assert_eq!(exports.len(), 11);711712let (name, run_ty) = exports.next().unwrap();713assert_eq!(name, "run");714let ComponentItem::ComponentFunc(run_ty) = run_ty else {715panic!("`run` export item of wrong type")716};717assert_eq!(run_ty.params().len(), 0);718719let mut run_results = run_ty.results();720assert_eq!(run_results.len(), 1);721assert_eq!(run_results.next().unwrap(), types::Type::U32);722723let (name, i_ty) = exports.next().unwrap();724assert_eq!(name, "i");725let ComponentItem::ComponentInstance(i_ty) = i_ty else {726panic!("`i` export item of wrong type")727};728let mut i_ty_exports = i_ty.exports(linker.engine());729assert_eq!(i_ty_exports.len(), 1);730let (name, i_i_ty) = i_ty_exports.next().unwrap();731assert_eq!(name, "i");732let ComponentItem::ComponentInstance(i_i_ty) = i_i_ty else {733panic!("`i.i` import item of wrong type")734};735let mut i_i_ty_exports = i_i_ty.exports(linker.engine());736assert_eq!(i_i_ty_exports.len(), 1);737let (name, i_i_m_ty) = i_i_ty_exports.next().unwrap();738assert_eq!(name, "m");739let ComponentItem::Module(i_i_m_ty) = i_i_m_ty else {740panic!("`i.i.m` import item of wrong type")741};742assert_eq!(i_i_m_ty.imports(linker.engine()).len(), 0);743assert_eq!(i_i_m_ty.exports(linker.engine()).len(), 0);744745let (name, r_ty) = exports.next().unwrap();746assert_eq!(name, "r");747let ComponentItem::ComponentInstance(r_ty) = r_ty else {748panic!("`r` export item of wrong type")749};750assert_eq!(r_ty.exports(linker.engine()).len(), 0);751752let (name, r2_ty) = exports.next().unwrap();753assert_eq!(name, "r2");754let ComponentItem::ComponentInstance(r2_ty) = r2_ty else {755panic!("`r2` export item of wrong type")756};757let mut r2_exports = r2_ty.exports(linker.engine());758assert_eq!(r2_exports.len(), 1);759let (name, r2_m_ty) = r2_exports.next().unwrap();760assert_eq!(name, "m");761let ComponentItem::Module(r2_m_ty) = r2_m_ty else {762panic!("`r2.m` export item of wrong type")763};764assert_eq!(r2_m_ty.imports(linker.engine()).len(), 0);765assert_eq!(r2_m_ty.exports(linker.engine()).len(), 0);766767let (name, b_ty) = exports.next().unwrap();768assert_eq!(name, "b");769let ComponentItem::Type(b_ty) = b_ty else {770panic!("`b` export item of wrong type")771};772assert_eq!(b_ty.unwrap_enum().names().collect::<Vec<_>>(), ["a", "b"]);773774let (name, c_ty) = exports.next().unwrap();775assert_eq!(name, "c");776let ComponentItem::Type(c_ty) = c_ty else {777panic!("`c` export item of wrong type")778};779let mut fields = c_ty.unwrap_record().fields();780{781let Field { name, ty } = fields.next().unwrap();782assert_eq!(name, "D");783assert_eq!(ty, types::Type::Bool);784let Field { name, ty } = fields.next().unwrap();785assert_eq!(name, "E");786assert_eq!(ty, types::Type::U32);787}788789let (name, f_ty) = exports.next().unwrap();790assert_eq!(name, "f");791let ComponentItem::Type(f_ty) = f_ty else {792panic!("`f` export item of wrong type")793};794assert_eq!(795f_ty.unwrap_flags().names().collect::<Vec<_>>(),796["G", "H", "I"]797);798799let (name, m_ty) = exports.next().unwrap();800assert_eq!(name, "m");801let ComponentItem::Type(m_ty) = m_ty else {802panic!("`m` export item of wrong type")803};804{805let mut fields = m_ty.unwrap_record().fields();806let Field { name, ty } = fields.next().unwrap();807assert_eq!(name, "N");808assert_eq!(ty, types::Type::Bool);809let Field { name, ty } = fields.next().unwrap();810assert_eq!(name, "O");811assert_eq!(ty, types::Type::U32);812}813814let (name, j_ty) = exports.next().unwrap();815assert_eq!(name, "j");816let ComponentItem::Type(j_ty) = j_ty else {817panic!("`j` export item of wrong type")818};819let mut cases = j_ty.unwrap_variant().cases();820{821let Case { name, ty } = cases.next().unwrap();822assert_eq!(name, "K");823assert_eq!(ty, Some(types::Type::U32));824let Case { name, ty } = cases.next().unwrap();825assert_eq!(name, "L");826assert_eq!(ty, Some(types::Type::Float64));827let Case { name, ty } = cases.next().unwrap();828assert_eq!(name, "M");829assert_eq!(ty, Some(m_ty));830}831832let (name, foo_ty) = exports.next().unwrap();833assert_eq!(name, "foo");834let ComponentItem::Type(foo_ty) = foo_ty else {835panic!("`foo` export item of wrong type")836};837{838let mut fields = foo_ty.unwrap_record().fields();839assert_eq!(fields.len(), 17);840let Field { name, ty } = fields.next().unwrap();841assert_eq!(name, "A");842assert_eq!(ty, types::Type::U32);843let Field { name, ty } = fields.next().unwrap();844assert_eq!(name, "B");845assert_eq!(ty, b_ty);846let Field { name, ty } = fields.next().unwrap();847assert_eq!(name, "C");848assert_eq!(ty, c_ty);849let Field { name, ty } = fields.next().unwrap();850assert_eq!(name, "F");851let ty = ty.unwrap_list();852assert_eq!(ty.ty(), f_ty);853let Field { name, ty } = fields.next().unwrap();854assert_eq!(name, "J");855assert_eq!(ty, j_ty);856let Field { name, ty } = fields.next().unwrap();857assert_eq!(name, "P");858assert_eq!(ty, types::Type::S8);859let Field { name, ty } = fields.next().unwrap();860assert_eq!(name, "Q");861assert_eq!(ty, types::Type::S16);862let Field { name, ty } = fields.next().unwrap();863assert_eq!(name, "R");864assert_eq!(ty, types::Type::S32);865let Field { name, ty } = fields.next().unwrap();866assert_eq!(name, "S");867assert_eq!(ty, types::Type::S64);868let Field { name, ty } = fields.next().unwrap();869assert_eq!(name, "T");870assert_eq!(ty, types::Type::Float32);871let Field { name, ty } = fields.next().unwrap();872assert_eq!(name, "U");873assert_eq!(ty, types::Type::Float64);874let Field { name, ty } = fields.next().unwrap();875assert_eq!(name, "V");876assert_eq!(ty, types::Type::String);877let Field { name, ty } = fields.next().unwrap();878assert_eq!(name, "W");879assert_eq!(ty, types::Type::Char);880let Field { name, ty } = fields.next().unwrap();881assert_eq!(name, "Y");882assert_eq!(883ty.unwrap_tuple().types().collect::<Vec<_>>(),884[types::Type::U32, types::Type::U32]885);886let Field { name, ty } = fields.next().unwrap();887assert_eq!(name, "AA");888assert_eq!(ty.unwrap_option().ty(), types::Type::U32);889let Field { name, ty } = fields.next().unwrap();890assert_eq!(name, "BB");891let ty = ty.unwrap_result();892assert_eq!(ty.ok(), Some(types::Type::String));893assert_eq!(ty.err(), Some(types::Type::String));894let Field { name, ty } = fields.next().unwrap();895assert_eq!(name, "CC");896assert_eq!(*ty.unwrap_own(), res_ty);897}898899let (name, fn_ty) = exports.next().unwrap();900assert_eq!(name, "fn");901let ComponentItem::ComponentFunc(fn_ty) = fn_ty else {902panic!("`fn` export item of wrong type")903};904let mut params = fn_ty.params();905assert_eq!(params.len(), 1);906let (name, param) = params.next().unwrap();907assert_eq!(name, "x");908assert_eq!(param.unwrap_option().ty(), foo_ty);909910let mut results = fn_ty.results();911assert_eq!(results.len(), 1);912assert_eq!(913results914.next()915.unwrap()916.unwrap_option()917.ty()918.unwrap_tuple()919.types()920.collect::<Vec<_>>(),921[types::Type::U32, types::Type::U32]922);923Ok(())924}925926927