1 #![cfg(not(miri))] 2 3 use super::{Param, Type, make_echo_component, make_echo_component_with_params}; 4 use anyhow::Result; 5 use wasmtime::component::types::{self, Case, ComponentItem, Field}; 6 use wasmtime::component::{Component, Linker, ResourceType, Val}; 7 use wasmtime::{Module, Store}; 8 use wasmtime_component_util::REALLOC_AND_FREE; 9 use wasmtime_test_util::component::FuncExt; 10 11 #[test] 12 fn primitives() -> Result<()> { 13 let engine = super::engine(); 14 let mut store = Store::new(&engine, ()); 15 let mut output = [Val::Bool(false)]; 16 17 for (input, ty, param) in [ 18 (Val::Bool(true), "bool", Param(Type::U8, Some(0))), 19 (Val::S8(-42), "s8", Param(Type::S8, Some(0))), 20 (Val::U8(42), "u8", Param(Type::U8, Some(0))), 21 (Val::S16(-4242), "s16", Param(Type::S16, Some(0))), 22 (Val::U16(4242), "u16", Param(Type::U16, Some(0))), 23 (Val::S32(-314159265), "s32", Param(Type::I32, Some(0))), 24 (Val::U32(314159265), "u32", Param(Type::I32, Some(0))), 25 (Val::S64(-31415926535897), "s64", Param(Type::I64, Some(0))), 26 (Val::U64(31415926535897), "u64", Param(Type::I64, Some(0))), 27 ( 28 Val::Float32(3.14159265), 29 "float32", 30 Param(Type::F32, Some(0)), 31 ), 32 ( 33 Val::Float64(3.14159265), 34 "float64", 35 Param(Type::F64, Some(0)), 36 ), 37 (Val::Char(''), "char", Param(Type::I32, Some(0))), 38 ] { 39 let component = Component::new(&engine, make_echo_component_with_params(ty, &[param]))?; 40 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 41 let func = instance.get_func(&mut store, "echo").unwrap(); 42 func.call_and_post_return(&mut store, &[input.clone()], &mut output)?; 43 44 assert_eq!(input, output[0]); 45 } 46 47 // Sad path: type mismatch 48 49 let component = Component::new( 50 &engine, 51 make_echo_component_with_params("float64", &[Param(Type::F64, Some(0))]), 52 )?; 53 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 54 let func = instance.get_func(&mut store, "echo").unwrap(); 55 let err = func 56 .call_and_post_return(&mut store, &[Val::U64(42)], &mut output) 57 .unwrap_err(); 58 59 assert!(err.to_string().contains("type mismatch"), "{err}"); 60 61 // Sad path: arity mismatch (too many) 62 63 let err = func 64 .call_and_post_return( 65 &mut store, 66 &[Val::Float64(3.14159265), Val::Float64(3.14159265)], 67 &mut output, 68 ) 69 .unwrap_err(); 70 71 assert!( 72 err.to_string().contains("expected 1 argument(s), got 2"), 73 "{err}" 74 ); 75 76 // Sad path: arity mismatch (too few) 77 78 let err = func 79 .call_and_post_return(&mut store, &[], &mut output) 80 .unwrap_err(); 81 assert!( 82 err.to_string().contains("expected 1 argument(s), got 0"), 83 "{err}" 84 ); 85 86 let err = func 87 .call_and_post_return(&mut store, &output, &mut []) 88 .unwrap_err(); 89 assert!( 90 err.to_string().contains("expected 1 result(s), got 0"), 91 "{err}" 92 ); 93 94 Ok(()) 95 } 96 97 #[test] 98 fn strings() -> Result<()> { 99 let engine = super::engine(); 100 let mut store = Store::new(&engine, ()); 101 102 let component = Component::new(&engine, make_echo_component("string", 8))?; 103 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 104 let func = instance.get_func(&mut store, "echo").unwrap(); 105 let input = Val::String("hello, component!".into()); 106 let mut output = [Val::Bool(false)]; 107 func.call_and_post_return(&mut store, &[input.clone()], &mut output)?; 108 assert_eq!(input, output[0]); 109 110 Ok(()) 111 } 112 113 #[test] 114 fn lists() -> Result<()> { 115 let engine = super::engine(); 116 let mut store = Store::new(&engine, ()); 117 118 let component = Component::new(&engine, make_echo_component("(list u32)", 8))?; 119 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 120 let func = instance.get_func(&mut store, "echo").unwrap(); 121 let input = Val::List(vec![ 122 Val::U32(32343), 123 Val::U32(79023439), 124 Val::U32(2084037802), 125 ]); 126 let mut output = [Val::Bool(false)]; 127 func.call_and_post_return(&mut store, &[input.clone()], &mut output)?; 128 129 assert_eq!(input, output[0]); 130 131 // Sad path: type mismatch 132 133 let err = Val::List(vec![ 134 Val::U32(32343), 135 Val::U32(79023439), 136 Val::Float32(3.14159265), 137 ]); 138 let err = func 139 .call_and_post_return(&mut store, &[err], &mut output) 140 .unwrap_err(); 141 assert!(err.to_string().contains("type mismatch"), "{err}"); 142 143 Ok(()) 144 } 145 146 #[test] 147 fn records() -> Result<()> { 148 let engine = super::engine(); 149 let mut store = Store::new(&engine, ()); 150 151 let component = Component::new( 152 &engine, 153 make_echo_component_with_params( 154 r#" 155 (type $c' (record 156 (field "D" bool) 157 (field "E" u32) 158 )) 159 (export $c "c" (type $c')) 160 (type $Foo' (record 161 (field "A" u32) 162 (field "B" float64) 163 (field "C" $c) 164 )) 165 "#, 166 &[ 167 Param(Type::I32, Some(0)), 168 Param(Type::F64, Some(8)), 169 Param(Type::U8, Some(16)), 170 Param(Type::I32, Some(20)), 171 ], 172 ), 173 )?; 174 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 175 let func = instance.get_func(&mut store, "echo").unwrap(); 176 let input = Val::Record(vec![ 177 ("A".into(), Val::U32(32343)), 178 ("B".into(), Val::Float64(3.14159265)), 179 ( 180 "C".into(), 181 Val::Record(vec![ 182 ("D".into(), Val::Bool(false)), 183 ("E".into(), Val::U32(2084037802)), 184 ]), 185 ), 186 ]); 187 let mut output = [Val::Bool(false)]; 188 func.call_and_post_return(&mut store, &[input.clone()], &mut output)?; 189 190 assert_eq!(input, output[0]); 191 192 // Sad path: type mismatch 193 194 let err = Val::Record(vec![ 195 ("A".into(), Val::S32(32343)), 196 ("B".into(), Val::Float64(3.14159265)), 197 ( 198 "C".into(), 199 Val::Record(vec![ 200 ("D".into(), Val::Bool(false)), 201 ("E".into(), Val::U32(2084037802)), 202 ]), 203 ), 204 ]); 205 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 206 let func = instance.get_func(&mut store, "echo").unwrap(); 207 let err = func 208 .call_and_post_return(&mut store, &[err], &mut output) 209 .unwrap_err(); 210 assert!(err.to_string().contains("type mismatch"), "{err}"); 211 212 // Sad path: too many fields 213 214 let err = Val::Record(vec![ 215 ("A".into(), Val::U32(32343)), 216 ("B".into(), Val::Float64(3.14159265)), 217 ( 218 "C".into(), 219 Val::Record(vec![ 220 ("D".into(), Val::Bool(false)), 221 ("E".into(), Val::U32(2084037802)), 222 ]), 223 ), 224 ("F".into(), Val::Bool(true)), 225 ]); 226 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 227 let func = instance.get_func(&mut store, "echo").unwrap(); 228 let err = func 229 .call_and_post_return(&mut store, &[err], &mut output) 230 .unwrap_err(); 231 assert!( 232 err.to_string().contains("expected 3 fields, got 4"), 233 "{err}" 234 ); 235 236 // Sad path: too few fields 237 238 let err = Val::Record(vec![ 239 ("A".into(), Val::U32(32343)), 240 ("B".into(), Val::Float64(3.14159265)), 241 ]); 242 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 243 let func = instance.get_func(&mut store, "echo").unwrap(); 244 let err = func 245 .call_and_post_return(&mut store, &[err], &mut output) 246 .unwrap_err(); 247 assert!( 248 err.to_string().contains("expected 3 fields, got 2"), 249 "{err}" 250 ); 251 252 Ok(()) 253 } 254 255 #[test] 256 fn variants() -> Result<()> { 257 let engine = super::engine(); 258 let mut store = Store::new(&engine, ()); 259 260 let fragment = r#" 261 (type $c' (record (field "D" bool) (field "E" u32))) 262 (export $c "c" (type $c')) 263 (type $Foo' (variant 264 (case "A" u32) 265 (case "B" float64) 266 (case "C" $c) 267 )) 268 "#; 269 270 let component = Component::new( 271 &engine, 272 make_echo_component_with_params( 273 fragment, 274 &[ 275 Param(Type::U8, Some(0)), 276 Param(Type::I64, Some(8)), 277 Param(Type::I32, None), 278 ], 279 ), 280 )?; 281 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 282 let func = instance.get_func(&mut store, "echo").unwrap(); 283 let input = Val::Variant("B".into(), Some(Box::new(Val::Float64(3.14159265)))); 284 let mut output = [Val::Bool(false)]; 285 func.call_and_post_return(&mut store, &[input.clone()], &mut output)?; 286 287 assert_eq!(input, output[0]); 288 289 // Do it again, this time using case "C" 290 291 let component = Component::new( 292 &engine, 293 make_echo_component_with_params( 294 fragment, 295 &[ 296 Param(Type::U8, Some(0)), 297 Param(Type::I64, Some(8)), 298 Param(Type::I32, Some(12)), 299 ], 300 ), 301 )?; 302 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 303 let func = instance.get_func(&mut store, "echo").unwrap(); 304 let input = Val::Variant( 305 "C".into(), 306 Some(Box::new(Val::Record(vec![ 307 ("D".into(), Val::Bool(true)), 308 ("E".into(), Val::U32(314159265)), 309 ]))), 310 ); 311 func.call_and_post_return(&mut store, &[input.clone()], &mut output)?; 312 313 assert_eq!(input, output[0]); 314 315 // Sad path: type mismatch 316 317 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 318 let func = instance.get_func(&mut store, "echo").unwrap(); 319 let err = Val::Variant("B".into(), Some(Box::new(Val::U64(314159265)))); 320 let err = func 321 .call_and_post_return(&mut store, &[err], &mut output) 322 .unwrap_err(); 323 assert!(err.to_string().contains("type mismatch"), "{err}"); 324 325 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 326 let func = instance.get_func(&mut store, "echo").unwrap(); 327 let err = Val::Variant("B".into(), None); 328 let err = func 329 .call_and_post_return(&mut store, &[err], &mut output) 330 .unwrap_err(); 331 assert!( 332 err.to_string().contains("expected a payload for case `B`"), 333 "{err}" 334 ); 335 336 // Sad path: unknown case 337 338 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 339 let func = instance.get_func(&mut store, "echo").unwrap(); 340 let err = Val::Variant("D".into(), Some(Box::new(Val::U64(314159265)))); 341 let err = func 342 .call_and_post_return(&mut store, &[err], &mut output) 343 .unwrap_err(); 344 assert!(err.to_string().contains("unknown variant case"), "{err}"); 345 346 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 347 let func = instance.get_func(&mut store, "echo").unwrap(); 348 let err = Val::Variant("D".into(), None); 349 let err = func 350 .call_and_post_return(&mut store, &[err], &mut output) 351 .unwrap_err(); 352 assert!(err.to_string().contains("unknown variant case"), "{err}"); 353 354 // Make sure we lift variants which have cases of different sizes with the correct alignment 355 356 let component = Component::new( 357 &engine, 358 make_echo_component_with_params( 359 r#" 360 (type $c' (record (field "D" bool) (field "E" u32))) 361 (export $c "c" (type $c')) 362 (type $a' (variant 363 (case "A" u32) 364 (case "B" float64) 365 (case "C" $c) 366 )) 367 (export $a "a" (type $a')) 368 (type $Foo' (record 369 (field "A" $a) 370 (field "B" u32) 371 )) 372 "#, 373 &[ 374 Param(Type::U8, Some(0)), 375 Param(Type::I64, Some(8)), 376 Param(Type::I32, None), 377 Param(Type::I32, Some(16)), 378 ], 379 ), 380 )?; 381 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 382 let func = instance.get_func(&mut store, "echo").unwrap(); 383 let input = Val::Record(vec![ 384 ( 385 "A".into(), 386 Val::Variant("A".into(), Some(Box::new(Val::U32(314159265)))), 387 ), 388 ("B".into(), Val::U32(628318530)), 389 ]); 390 func.call_and_post_return(&mut store, &[input.clone()], &mut output)?; 391 392 assert_eq!(input, output[0]); 393 394 Ok(()) 395 } 396 397 #[test] 398 fn flags() -> Result<()> { 399 let engine = super::engine(); 400 let mut store = Store::new(&engine, ()); 401 402 let component = Component::new( 403 &engine, 404 make_echo_component_with_params( 405 r#"(flags "A" "B" "C" "D" "E")"#, 406 &[Param(Type::U8, Some(0))], 407 ), 408 )?; 409 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 410 let func = instance.get_func(&mut store, "echo").unwrap(); 411 let input = Val::Flags(vec!["B".into(), "D".into()]); 412 let mut output = [Val::Bool(false)]; 413 func.call_and_post_return(&mut store, &[input.clone()], &mut output)?; 414 415 assert_eq!(input, output[0]); 416 417 // Sad path: unknown flags 418 419 let err = Val::Flags(vec!["B".into(), "D".into(), "F".into()]); 420 let err = func 421 .call_and_post_return(&mut store, &[err], &mut output) 422 .unwrap_err(); 423 assert!(err.to_string().contains("unknown flag"), "{err}"); 424 425 Ok(()) 426 } 427 428 #[test] 429 fn everything() -> Result<()> { 430 // This serves to test both nested types and storing parameters on the heap (i.e. exceeding `MAX_STACK_PARAMS`) 431 432 let engine = super::engine(); 433 let mut store = Store::new(&engine, ()); 434 435 let component = Component::new( 436 &engine, 437 make_echo_component_with_params( 438 r#" 439 (type $b' (enum "a" "b")) 440 (export $b "b" (type $b')) 441 (type $c' (record (field "D" bool) (field "E" u32))) 442 (export $c "c" (type $c')) 443 (type $f' (flags "G" "H" "I")) 444 (export $f "f" (type $f')) 445 (type $m' (record (field "N" bool) (field "O" u32))) 446 (export $m "m" (type $m')) 447 (type $j' (variant 448 (case "K" u32) 449 (case "L" float64) 450 (case "M" $m) 451 )) 452 (export $j "j" (type $j')) 453 454 (type $Foo' (record 455 (field "A" u32) 456 (field "B" $b) 457 (field "C" $c) 458 (field "F" (list $f)) 459 (field "J" $j) 460 (field "P" s8) 461 (field "Q" s16) 462 (field "R" s32) 463 (field "S" s64) 464 (field "T" float32) 465 (field "U" float64) 466 (field "V" string) 467 (field "W" char) 468 (field "Y" (tuple u32 u32)) 469 (field "AA" (option u32)) 470 (field "BB" (result string (error string))) 471 )) 472 "#, 473 &[ 474 Param(Type::I32, Some(0)), 475 Param(Type::U8, Some(4)), 476 Param(Type::U8, Some(5)), 477 Param(Type::I32, Some(8)), 478 Param(Type::I32, Some(12)), 479 Param(Type::I32, Some(16)), 480 Param(Type::U8, Some(20)), 481 Param(Type::I64, Some(28)), 482 Param(Type::I32, Some(32)), 483 Param(Type::S8, Some(36)), 484 Param(Type::S16, Some(38)), 485 Param(Type::I32, Some(40)), 486 Param(Type::I64, Some(48)), 487 Param(Type::F32, Some(56)), 488 Param(Type::F64, Some(64)), 489 Param(Type::I32, Some(72)), 490 Param(Type::I32, Some(76)), 491 Param(Type::I32, Some(80)), 492 Param(Type::I32, Some(84)), 493 Param(Type::I32, Some(88)), 494 Param(Type::I64, Some(96)), 495 Param(Type::U8, Some(104)), 496 Param(Type::I32, Some(108)), 497 Param(Type::U8, Some(112)), 498 Param(Type::I32, Some(116)), 499 Param(Type::I32, Some(120)), 500 ], 501 ), 502 )?; 503 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 504 let func = instance.get_func(&mut store, "echo").unwrap(); 505 let input = Val::Record(vec![ 506 ("A".into(), Val::U32(32343)), 507 ("B".into(), Val::Enum("b".to_string())), 508 ( 509 "C".into(), 510 Val::Record(vec![ 511 ("D".to_string(), Val::Bool(false)), 512 ("E".to_string(), Val::U32(2084037802)), 513 ]), 514 ), 515 ( 516 "F".into(), 517 Val::List(vec![Val::Flags(vec!["G".to_string(), "I".to_string()])]), 518 ), 519 ( 520 "J".into(), 521 Val::Variant("L".to_string(), Some(Box::new(Val::Float64(3.14159265)))), 522 ), 523 ("P".into(), Val::S8(42)), 524 ("Q".into(), Val::S16(4242)), 525 ("R".into(), Val::S32(42424242)), 526 ("S".into(), Val::S64(424242424242424242)), 527 ("T".into(), Val::Float32(3.14159265)), 528 ("U".into(), Val::Float64(3.14159265)), 529 ("V".into(), Val::String("wow, nice types".to_string())), 530 ("W".into(), Val::Char('')), 531 ("Y".into(), Val::Tuple(vec![Val::U32(42), Val::U32(24)])), 532 ( 533 "AA".into(), 534 Val::Option(Some(Box::new(Val::U32(314159265)))), 535 ), 536 ( 537 "BB".into(), 538 Val::Result(Ok(Some(Box::new(Val::String("no problem".to_string()))))), 539 ), 540 ]); 541 let mut output = [Val::Bool(false)]; 542 func.call_and_post_return(&mut store, &[input.clone()], &mut output)?; 543 544 assert_eq!(input, output[0]); 545 546 Ok(()) 547 } 548 549 #[test] 550 fn introspection() -> Result<()> { 551 let engine = super::engine(); 552 553 let component = Component::new( 554 &engine, 555 format!( 556 r#" 557 (component 558 (import "res" (type $res (sub resource))) 559 560 (import "ai" (instance $i)) 561 (import "bi" (instance $i2 (export "m" (core module)))) 562 563 (alias export $i2 "m" (core module $m)) 564 565 (type $t (func (param "a" u32) (result u32))) 566 (component $a 567 (core module $m 568 (func (export "add-five") (param i32) (result i32) 569 local.get 0 570 i32.const 5 571 i32.add) 572 ) 573 (core instance $m (instantiate $m)) 574 (func (export "add-five") (type $t) (canon lift (core func $m "add-five"))) 575 ) 576 (component $b 577 (import "interface-v1" (instance $i 578 (export "add-five" (func (type $t))))) 579 (core module $m 580 (func $add-five (import "interface-0.1.0" "add-five") (param i32) (result i32)) 581 (func) ;; causes index out of bounds 582 (func (export "run") (result i32) i32.const 0 call $add-five) 583 ) 584 (core func $add-five (canon lower (func $i "add-five"))) 585 (core instance $i (instantiate 0 586 (with "interface-0.1.0" (instance 587 (export "add-five" (func $add-five)) 588 )) 589 )) 590 (func (result u32) (canon lift (core func $i "run"))) 591 (export "run" (func 1)) 592 ) 593 (instance $a (instantiate $a)) 594 (instance $b (instantiate $b (with "interface-v1" (instance $a)))) 595 (export "run" (func $b "run")) 596 597 (component $c 598 (component $c 599 (export "m" (core module $m)) 600 ) 601 (instance $c (instantiate $c)) 602 (export "i" (instance $c)) 603 ) 604 (instance $c (instantiate $c)) 605 (export "i" (instance $c)) 606 (export "r" (instance $i)) 607 (export "r2" (instance $i2)) 608 609 (type $b' (enum "a" "b")) 610 (export $b "b" (type $b')) 611 (type $c' (record (field "D" bool) (field "E" u32))) 612 (export $c "c" (type $c')) 613 (type $f' (flags "G" "H" "I")) 614 (export $f "f" (type $f')) 615 (type $m' (record (field "N" bool) (field "O" u32))) 616 (export $m "m" (type $m')) 617 (type $j' (variant 618 (case "K" u32) 619 (case "L" float64) 620 (case "M" $m) 621 )) 622 (export $j "j" (type $j')) 623 624 (type $Foo' (record 625 (field "A" u32) 626 (field "B" $b) 627 (field "C" $c) 628 (field "F" (list $f)) 629 (field "J" $j) 630 (field "P" s8) 631 (field "Q" s16) 632 (field "R" s32) 633 (field "S" s64) 634 (field "T" float32) 635 (field "U" float64) 636 (field "V" string) 637 (field "W" char) 638 (field "Y" (tuple u32 u32)) 639 (field "AA" (option u32)) 640 (field "BB" (result string (error string))) 641 (field "CC" (own $res)) 642 )) 643 (export $Foo "foo" (type $Foo')) 644 645 (core module $m2 646 (func (export "f") (param i32) (result i32) 647 local.get 0 648 ) 649 (memory (export "memory") 1) 650 {REALLOC_AND_FREE} 651 ) 652 (core instance $i3 (instantiate $m2)) 653 654 (func (export "fn") (param "x" (option $Foo)) (result (option (tuple u32 u32))) 655 (canon lift 656 (core func $i3 "f") 657 (memory $i3 "memory") 658 (realloc (func $i3 "realloc")) 659 ) 660 ) 661 ) 662 "# 663 ), 664 )?; 665 666 struct MyType; 667 668 let mut linker = Linker::<()>::new(&engine); 669 linker 670 .root() 671 .resource("res", ResourceType::host::<MyType>(), |_, _| Ok(()))?; 672 linker.instance("ai")?; 673 linker 674 .instance("bi")? 675 .module("m", &Module::new(&engine, "(module)")?)?; 676 677 let component_ty = linker.substituted_component_type(&component)?; 678 679 let mut imports = component_ty.imports(linker.engine()); 680 assert_eq!(imports.len(), 3); 681 let (name, res_ty) = imports.next().unwrap(); 682 assert_eq!(name, "res"); 683 let ComponentItem::Resource(res_ty) = res_ty else { 684 panic!("`res` import item of wrong type") 685 }; 686 assert_eq!(res_ty, ResourceType::host::<MyType>()); 687 688 let (name, ai_ty) = imports.next().unwrap(); 689 assert_eq!(name, "ai"); 690 let ComponentItem::ComponentInstance(ai_ty) = ai_ty else { 691 panic!("`ai` import item of wrong type") 692 }; 693 assert_eq!(ai_ty.exports(linker.engine()).len(), 0); 694 695 let (name, bi_ty) = imports.next().unwrap(); 696 assert_eq!(name, "bi"); 697 let ComponentItem::ComponentInstance(bi_ty) = bi_ty else { 698 panic!("`bi` import item of wrong type") 699 }; 700 let mut bi_exports = bi_ty.exports(linker.engine()); 701 assert_eq!(bi_exports.len(), 1); 702 let (name, bi_m_ty) = bi_exports.next().unwrap(); 703 assert_eq!(name, "m"); 704 let ComponentItem::Module(bi_m_ty) = bi_m_ty else { 705 panic!("`bi.m` import item of wrong type") 706 }; 707 assert_eq!(bi_m_ty.imports(linker.engine()).len(), 0); 708 assert_eq!(bi_m_ty.exports(linker.engine()).len(), 0); 709 710 let mut exports = component_ty.exports(linker.engine()); 711 assert_eq!(exports.len(), 11); 712 713 let (name, run_ty) = exports.next().unwrap(); 714 assert_eq!(name, "run"); 715 let ComponentItem::ComponentFunc(run_ty) = run_ty else { 716 panic!("`run` export item of wrong type") 717 }; 718 assert_eq!(run_ty.params().len(), 0); 719 720 let mut run_results = run_ty.results(); 721 assert_eq!(run_results.len(), 1); 722 assert_eq!(run_results.next().unwrap(), types::Type::U32); 723 724 let (name, i_ty) = exports.next().unwrap(); 725 assert_eq!(name, "i"); 726 let ComponentItem::ComponentInstance(i_ty) = i_ty else { 727 panic!("`i` export item of wrong type") 728 }; 729 let mut i_ty_exports = i_ty.exports(linker.engine()); 730 assert_eq!(i_ty_exports.len(), 1); 731 let (name, i_i_ty) = i_ty_exports.next().unwrap(); 732 assert_eq!(name, "i"); 733 let ComponentItem::ComponentInstance(i_i_ty) = i_i_ty else { 734 panic!("`i.i` import item of wrong type") 735 }; 736 let mut i_i_ty_exports = i_i_ty.exports(linker.engine()); 737 assert_eq!(i_i_ty_exports.len(), 1); 738 let (name, i_i_m_ty) = i_i_ty_exports.next().unwrap(); 739 assert_eq!(name, "m"); 740 let ComponentItem::Module(i_i_m_ty) = i_i_m_ty else { 741 panic!("`i.i.m` import item of wrong type") 742 }; 743 assert_eq!(i_i_m_ty.imports(linker.engine()).len(), 0); 744 assert_eq!(i_i_m_ty.exports(linker.engine()).len(), 0); 745 746 let (name, r_ty) = exports.next().unwrap(); 747 assert_eq!(name, "r"); 748 let ComponentItem::ComponentInstance(r_ty) = r_ty else { 749 panic!("`r` export item of wrong type") 750 }; 751 assert_eq!(r_ty.exports(linker.engine()).len(), 0); 752 753 let (name, r2_ty) = exports.next().unwrap(); 754 assert_eq!(name, "r2"); 755 let ComponentItem::ComponentInstance(r2_ty) = r2_ty else { 756 panic!("`r2` export item of wrong type") 757 }; 758 let mut r2_exports = r2_ty.exports(linker.engine()); 759 assert_eq!(r2_exports.len(), 1); 760 let (name, r2_m_ty) = r2_exports.next().unwrap(); 761 assert_eq!(name, "m"); 762 let ComponentItem::Module(r2_m_ty) = r2_m_ty else { 763 panic!("`r2.m` export item of wrong type") 764 }; 765 assert_eq!(r2_m_ty.imports(linker.engine()).len(), 0); 766 assert_eq!(r2_m_ty.exports(linker.engine()).len(), 0); 767 768 let (name, b_ty) = exports.next().unwrap(); 769 assert_eq!(name, "b"); 770 let ComponentItem::Type(b_ty) = b_ty else { 771 panic!("`b` export item of wrong type") 772 }; 773 assert_eq!(b_ty.unwrap_enum().names().collect::<Vec<_>>(), ["a", "b"]); 774 775 let (name, c_ty) = exports.next().unwrap(); 776 assert_eq!(name, "c"); 777 let ComponentItem::Type(c_ty) = c_ty else { 778 panic!("`c` export item of wrong type") 779 }; 780 let mut fields = c_ty.unwrap_record().fields(); 781 { 782 let Field { name, ty } = fields.next().unwrap(); 783 assert_eq!(name, "D"); 784 assert_eq!(ty, types::Type::Bool); 785 let Field { name, ty } = fields.next().unwrap(); 786 assert_eq!(name, "E"); 787 assert_eq!(ty, types::Type::U32); 788 } 789 790 let (name, f_ty) = exports.next().unwrap(); 791 assert_eq!(name, "f"); 792 let ComponentItem::Type(f_ty) = f_ty else { 793 panic!("`f` export item of wrong type") 794 }; 795 assert_eq!( 796 f_ty.unwrap_flags().names().collect::<Vec<_>>(), 797 ["G", "H", "I"] 798 ); 799 800 let (name, m_ty) = exports.next().unwrap(); 801 assert_eq!(name, "m"); 802 let ComponentItem::Type(m_ty) = m_ty else { 803 panic!("`m` export item of wrong type") 804 }; 805 { 806 let mut fields = m_ty.unwrap_record().fields(); 807 let Field { name, ty } = fields.next().unwrap(); 808 assert_eq!(name, "N"); 809 assert_eq!(ty, types::Type::Bool); 810 let Field { name, ty } = fields.next().unwrap(); 811 assert_eq!(name, "O"); 812 assert_eq!(ty, types::Type::U32); 813 } 814 815 let (name, j_ty) = exports.next().unwrap(); 816 assert_eq!(name, "j"); 817 let ComponentItem::Type(j_ty) = j_ty else { 818 panic!("`j` export item of wrong type") 819 }; 820 let mut cases = j_ty.unwrap_variant().cases(); 821 { 822 let Case { name, ty } = cases.next().unwrap(); 823 assert_eq!(name, "K"); 824 assert_eq!(ty, Some(types::Type::U32)); 825 let Case { name, ty } = cases.next().unwrap(); 826 assert_eq!(name, "L"); 827 assert_eq!(ty, Some(types::Type::Float64)); 828 let Case { name, ty } = cases.next().unwrap(); 829 assert_eq!(name, "M"); 830 assert_eq!(ty, Some(m_ty)); 831 } 832 833 let (name, foo_ty) = exports.next().unwrap(); 834 assert_eq!(name, "foo"); 835 let ComponentItem::Type(foo_ty) = foo_ty else { 836 panic!("`foo` export item of wrong type") 837 }; 838 { 839 let mut fields = foo_ty.unwrap_record().fields(); 840 assert_eq!(fields.len(), 17); 841 let Field { name, ty } = fields.next().unwrap(); 842 assert_eq!(name, "A"); 843 assert_eq!(ty, types::Type::U32); 844 let Field { name, ty } = fields.next().unwrap(); 845 assert_eq!(name, "B"); 846 assert_eq!(ty, b_ty); 847 let Field { name, ty } = fields.next().unwrap(); 848 assert_eq!(name, "C"); 849 assert_eq!(ty, c_ty); 850 let Field { name, ty } = fields.next().unwrap(); 851 assert_eq!(name, "F"); 852 let ty = ty.unwrap_list(); 853 assert_eq!(ty.ty(), f_ty); 854 let Field { name, ty } = fields.next().unwrap(); 855 assert_eq!(name, "J"); 856 assert_eq!(ty, j_ty); 857 let Field { name, ty } = fields.next().unwrap(); 858 assert_eq!(name, "P"); 859 assert_eq!(ty, types::Type::S8); 860 let Field { name, ty } = fields.next().unwrap(); 861 assert_eq!(name, "Q"); 862 assert_eq!(ty, types::Type::S16); 863 let Field { name, ty } = fields.next().unwrap(); 864 assert_eq!(name, "R"); 865 assert_eq!(ty, types::Type::S32); 866 let Field { name, ty } = fields.next().unwrap(); 867 assert_eq!(name, "S"); 868 assert_eq!(ty, types::Type::S64); 869 let Field { name, ty } = fields.next().unwrap(); 870 assert_eq!(name, "T"); 871 assert_eq!(ty, types::Type::Float32); 872 let Field { name, ty } = fields.next().unwrap(); 873 assert_eq!(name, "U"); 874 assert_eq!(ty, types::Type::Float64); 875 let Field { name, ty } = fields.next().unwrap(); 876 assert_eq!(name, "V"); 877 assert_eq!(ty, types::Type::String); 878 let Field { name, ty } = fields.next().unwrap(); 879 assert_eq!(name, "W"); 880 assert_eq!(ty, types::Type::Char); 881 let Field { name, ty } = fields.next().unwrap(); 882 assert_eq!(name, "Y"); 883 assert_eq!( 884 ty.unwrap_tuple().types().collect::<Vec<_>>(), 885 [types::Type::U32, types::Type::U32] 886 ); 887 let Field { name, ty } = fields.next().unwrap(); 888 assert_eq!(name, "AA"); 889 assert_eq!(ty.unwrap_option().ty(), types::Type::U32); 890 let Field { name, ty } = fields.next().unwrap(); 891 assert_eq!(name, "BB"); 892 let ty = ty.unwrap_result(); 893 assert_eq!(ty.ok(), Some(types::Type::String)); 894 assert_eq!(ty.err(), Some(types::Type::String)); 895 let Field { name, ty } = fields.next().unwrap(); 896 assert_eq!(name, "CC"); 897 assert_eq!(*ty.unwrap_own(), res_ty); 898 } 899 900 let (name, fn_ty) = exports.next().unwrap(); 901 assert_eq!(name, "fn"); 902 let ComponentItem::ComponentFunc(fn_ty) = fn_ty else { 903 panic!("`fn` export item of wrong type") 904 }; 905 let mut params = fn_ty.params(); 906 assert_eq!(params.len(), 1); 907 let (name, param) = params.next().unwrap(); 908 assert_eq!(name, "x"); 909 assert_eq!(param.unwrap_option().ty(), foo_ty); 910 911 let mut results = fn_ty.results(); 912 assert_eq!(results.len(), 1); 913 assert_eq!( 914 results 915 .next() 916 .unwrap() 917 .unwrap_option() 918 .ty() 919 .unwrap_tuple() 920 .types() 921 .collect::<Vec<_>>(), 922 [types::Type::U32, types::Type::U32] 923 ); 924 Ok(()) 925 } 926