1 #![cfg(not(miri))] 2 3 use super::{Param, Type, make_echo_component, make_echo_component_with_params}; 4 use wasmtime::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 10 #[test] 11 fn primitives() -> Result<()> { 12 let engine = super::engine(); 13 let mut store = Store::new(&engine, ()); 14 let mut output = [Val::Bool(false)]; 15 16 for (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 ( 27 Val::Float32(3.14159265), 28 "float32", 29 Param(Type::F32, Some(0)), 30 ), 31 ( 32 Val::Float64(3.14159265), 33 "float64", 34 Param(Type::F64, Some(0)), 35 ), 36 (Val::Char(''), "char", Param(Type::I32, Some(0))), 37 ] { 38 let component = Component::new(&engine, make_echo_component_with_params(ty, &[param]))?; 39 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 40 let func = instance.get_func(&mut store, "echo").unwrap(); 41 func.call(&mut store, &[input.clone()], &mut output)?; 42 43 assert_eq!(input, output[0]); 44 } 45 46 // Sad path: type mismatch 47 48 let component = Component::new( 49 &engine, 50 make_echo_component_with_params("float64", &[Param(Type::F64, Some(0))]), 51 )?; 52 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 53 let func = instance.get_func(&mut store, "echo").unwrap(); 54 let err = func 55 .call(&mut store, &[Val::U64(42)], &mut output) 56 .unwrap_err(); 57 58 assert!(err.to_string().contains("type mismatch"), "{err}"); 59 60 // Sad path: arity mismatch (too many) 61 62 let err = func 63 .call( 64 &mut store, 65 &[Val::Float64(3.14159265), Val::Float64(3.14159265)], 66 &mut output, 67 ) 68 .unwrap_err(); 69 70 assert!( 71 err.to_string().contains("expected 1 argument(s), got 2"), 72 "{err}" 73 ); 74 75 // Sad path: arity mismatch (too few) 76 77 let err = func.call(&mut store, &[], &mut output).unwrap_err(); 78 assert!( 79 err.to_string().contains("expected 1 argument(s), got 0"), 80 "{err}" 81 ); 82 83 let err = func.call(&mut store, &output, &mut []).unwrap_err(); 84 assert!( 85 err.to_string().contains("expected 1 result(s), got 0"), 86 "{err}" 87 ); 88 89 Ok(()) 90 } 91 92 #[test] 93 fn strings() -> Result<()> { 94 let engine = super::engine(); 95 let mut store = Store::new(&engine, ()); 96 97 let component = Component::new(&engine, make_echo_component("string", 8))?; 98 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 99 let func = instance.get_func(&mut store, "echo").unwrap(); 100 let input = Val::String("hello, component!".into()); 101 let mut output = [Val::Bool(false)]; 102 func.call(&mut store, &[input.clone()], &mut output)?; 103 assert_eq!(input, output[0]); 104 105 Ok(()) 106 } 107 108 #[test] 109 fn lists() -> Result<()> { 110 let engine = super::engine(); 111 let mut store = Store::new(&engine, ()); 112 113 let component = Component::new(&engine, make_echo_component("(list u32)", 8))?; 114 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 115 let func = instance.get_func(&mut store, "echo").unwrap(); 116 let input = Val::List(vec![ 117 Val::U32(32343), 118 Val::U32(79023439), 119 Val::U32(2084037802), 120 ]); 121 let mut output = [Val::Bool(false)]; 122 func.call(&mut store, &[input.clone()], &mut output)?; 123 124 assert_eq!(input, output[0]); 125 126 // Sad path: type mismatch 127 128 let err = Val::List(vec![ 129 Val::U32(32343), 130 Val::U32(79023439), 131 Val::Float32(3.14159265), 132 ]); 133 let err = func.call(&mut store, &[err], &mut output).unwrap_err(); 134 assert!(err.to_string().contains("type mismatch"), "{err}"); 135 136 Ok(()) 137 } 138 139 #[test] 140 fn maps() -> Result<()> { 141 let engine = super::map_engine(); 142 let mut store = Store::new(&engine, ()); 143 144 let component = Component::new(&engine, make_echo_component("(map u32 string)", 8))?; 145 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 146 let func = instance.get_func(&mut store, "echo").unwrap(); 147 148 let input_map = vec![ 149 (Val::U32(1), Val::String("one".into())), 150 (Val::U32(2), Val::String("two".into())), 151 (Val::U32(3), Val::String("three".into())), 152 ]; 153 let input = Val::Map(input_map); 154 155 let mut output = [Val::Bool(false)]; 156 func.call(&mut store, &[input.clone()], &mut output)?; 157 158 // Maps should round-trip correctly 159 match &output[0] { 160 Val::Map(output_map) => { 161 assert_eq!(output_map.len(), 3); 162 assert!( 163 output_map 164 .iter() 165 .any(|(k, v)| *k == Val::U32(1) && *v == Val::String("one".into())) 166 ); 167 assert!( 168 output_map 169 .iter() 170 .any(|(k, v)| *k == Val::U32(2) && *v == Val::String("two".into())) 171 ); 172 assert!( 173 output_map 174 .iter() 175 .any(|(k, v)| *k == Val::U32(3) && *v == Val::String("three".into())) 176 ); 177 } 178 _ => panic!("expected map"), 179 } 180 181 // Sad path: type mismatch (wrong key type) 182 // Need to create a fresh instance because errors can leave the instance in a bad state 183 let mut store2 = Store::new(&engine, ()); 184 let instance2 = Linker::new(&engine).instantiate(&mut store2, &component)?; 185 let func2 = instance2.get_func(&mut store2, "echo").unwrap(); 186 187 let err_map = vec![(Val::String("key".into()), Val::String("value".into()))]; 188 let err = Val::Map(err_map); 189 let err = func2.call(&mut store2, &[err], &mut output).unwrap_err(); 190 assert!(err.to_string().contains("type mismatch"), "{err}"); 191 192 // Sad path: type mismatch (wrong value type) 193 let mut store3 = Store::new(&engine, ()); 194 let instance3 = Linker::new(&engine).instantiate(&mut store3, &component)?; 195 let func3 = instance3.get_func(&mut store3, "echo").unwrap(); 196 197 let err_map2 = vec![(Val::U32(1), Val::U32(42))]; 198 let err = Val::Map(err_map2); 199 let err = func3.call(&mut store3, &[err], &mut output).unwrap_err(); 200 assert!(err.to_string().contains("type mismatch"), "{err}"); 201 202 // Test empty map 203 let empty_map = vec![]; 204 let input = Val::Map(empty_map); 205 func.call(&mut store, &[input.clone()], &mut output)?; 206 match &output[0] { 207 Val::Map(output_map) => assert_eq!(output_map.len(), 0), 208 _ => panic!("expected map"), 209 } 210 211 Ok(()) 212 } 213 214 #[test] 215 fn maps_complex_types() -> Result<()> { 216 let engine = super::map_engine(); 217 let mut store = Store::new(&engine, ()); 218 219 // Test map<string, list<u32>> 220 let component = Component::new(&engine, make_echo_component("(map string (list u32))", 8))?; 221 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 222 let func = instance.get_func(&mut store, "echo").unwrap(); 223 224 let input_map = vec![ 225 ( 226 Val::String("first".into()), 227 Val::List(vec![Val::U32(1), Val::U32(2), Val::U32(3)]), 228 ), 229 ( 230 Val::String("second".into()), 231 Val::List(vec![Val::U32(4), Val::U32(5)]), 232 ), 233 ]; 234 let input = Val::Map(input_map); 235 236 let mut output = [Val::Bool(false)]; 237 func.call(&mut store, &[input.clone()], &mut output)?; 238 239 // Verify round-trip 240 match &output[0] { 241 Val::Map(output_map) => { 242 assert_eq!(output_map.len(), 2); 243 // Check first entry 244 let first_entry = output_map 245 .iter() 246 .find(|(k, _)| *k == Val::String("first".into())); 247 match first_entry { 248 Some((_, Val::List(list))) => { 249 assert_eq!(list.len(), 3); 250 assert_eq!(list[0], Val::U32(1)); 251 assert_eq!(list[1], Val::U32(2)); 252 assert_eq!(list[2], Val::U32(3)); 253 } 254 _ => panic!("expected list"), 255 } 256 // Check second entry 257 let second_entry = output_map 258 .iter() 259 .find(|(k, _)| *k == Val::String("second".into())); 260 match second_entry { 261 Some((_, Val::List(list))) => { 262 assert_eq!(list.len(), 2); 263 assert_eq!(list[0], Val::U32(4)); 264 assert_eq!(list[1], Val::U32(5)); 265 } 266 _ => panic!("expected list"), 267 } 268 } 269 _ => panic!("expected map"), 270 } 271 272 Ok(()) 273 } 274 275 #[test] 276 fn maps_equality() -> Result<()> { 277 let map1 = vec![ 278 (Val::U32(1), Val::String("one".into())), 279 (Val::U32(2), Val::String("two".into())), 280 ]; 281 282 let map2 = vec![ 283 (Val::U32(1), Val::String("one".into())), 284 (Val::U32(2), Val::String("two".into())), 285 ]; 286 287 // Maps with same content in same order should be equal 288 assert_eq!(Val::Map(map1.clone()), Val::Map(map2)); 289 290 // Different values should not be equal 291 let map3 = vec![ 292 (Val::U32(1), Val::String("different".into())), 293 (Val::U32(2), Val::String("two".into())), 294 ]; 295 assert_ne!(Val::Map(map1.clone()), Val::Map(map3)); 296 297 // Different keys should not be equal 298 let map4 = vec![ 299 (Val::U32(3), Val::String("one".into())), 300 (Val::U32(2), Val::String("two".into())), 301 ]; 302 assert_ne!(Val::Map(map1), Val::Map(map4)); 303 304 // Empty maps should be equal 305 let empty1: Vec<(Val, Val)> = vec![]; 306 let empty2: Vec<(Val, Val)> = vec![]; 307 assert_eq!(Val::Map(empty1), Val::Map(empty2)); 308 309 Ok(()) 310 } 311 312 #[test] 313 fn maps_duplicate_keys() -> Result<()> { 314 let engine = super::map_engine(); 315 let mut store = Store::new(&engine, ()); 316 317 let component = Component::new(&engine, make_echo_component("(map u32 string)", 8))?; 318 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 319 let func = instance.get_func(&mut store, "echo").unwrap(); 320 321 // Create a map with duplicate keys - Vec preserves all entries 322 let input_map = vec![ 323 (Val::U32(1), Val::String("first".into())), 324 (Val::U32(1), Val::String("last".into())), // Duplicate key 325 (Val::U32(2), Val::String("two".into())), 326 ]; 327 let input = Val::Map(input_map); 328 329 let mut output = [Val::Bool(false)]; 330 func.call(&mut store, &[input.clone()], &mut output)?; 331 332 // Verify all entries are preserved (Vec doesn't deduplicate) 333 match &output[0] { 334 Val::Map(output_map) => { 335 // Should have 3 entries (Vec preserves duplicates) 336 assert_eq!(output_map.len(), 3); 337 } 338 _ => panic!("expected map"), 339 } 340 341 Ok(()) 342 } 343 344 #[test] 345 fn maps_all_primitive_types() -> Result<()> { 346 let engine = super::map_engine(); 347 let mut store = Store::new(&engine, ()); 348 349 // Test map<u32, u32> 350 let component = Component::new(&engine, make_echo_component("(map u32 u32)", 8))?; 351 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 352 let func = instance.get_func(&mut store, "echo").unwrap(); 353 354 let input_map = vec![(Val::U32(1), Val::U32(100)), (Val::U32(2), Val::U32(200))]; 355 let input = Val::Map(input_map); 356 357 let mut output = [Val::Bool(false)]; 358 func.call(&mut store, &[input.clone()], &mut output)?; 359 assert_eq!(input, output[0]); 360 361 // Test map<string, u32> 362 let component = Component::new(&engine, make_echo_component("(map string u32)", 8))?; 363 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 364 let func = instance.get_func(&mut store, "echo").unwrap(); 365 366 let input_map = vec![ 367 (Val::String("one".into()), Val::U32(1)), 368 (Val::String("two".into()), Val::U32(2)), 369 ]; 370 let input = Val::Map(input_map); 371 372 func.call(&mut store, &[input.clone()], &mut output)?; 373 assert_eq!(input, output[0]); 374 375 Ok(()) 376 } 377 378 #[test] 379 fn maps_alignment() -> Result<()> { 380 let engine = super::map_engine(); 381 let mut store = Store::new(&engine, ()); 382 383 // Test map<u8, u64> - key_size=1, value_align=8 384 // This would fail with the alignment bug because value would be at offset 1 instead of 8 385 let component = Component::new(&engine, make_echo_component("(map u8 u64)", 8))?; 386 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 387 let func = instance.get_func(&mut store, "echo").unwrap(); 388 389 let input_map = vec![ 390 (Val::U8(1), Val::U64(100)), 391 (Val::U8(2), Val::U64(200)), 392 (Val::U8(3), Val::U64(300)), 393 ]; 394 let input = Val::Map(input_map); 395 396 let mut output = [Val::Bool(false)]; 397 func.call(&mut store, &[input.clone()], &mut output)?; 398 assert_eq!(input, output[0]); 399 400 // Test map<u32, u64> - key_size=4, value_align=8 401 // This would fail with the alignment bug because value would be at offset 4 instead of 8 402 let component = Component::new(&engine, make_echo_component("(map u32 u64)", 8))?; 403 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 404 let func = instance.get_func(&mut store, "echo").unwrap(); 405 406 let input_map = vec![(Val::U32(1), Val::U64(1000)), (Val::U32(2), Val::U64(2000))]; 407 let input = Val::Map(input_map); 408 409 func.call(&mut store, &[input.clone()], &mut output)?; 410 assert_eq!(input, output[0]); 411 412 // Test map<u8, u32> - key_size=1, value_align=4 413 // This would fail with the alignment bug because value would be at offset 1 instead of 4 414 let component = Component::new(&engine, make_echo_component("(map u8 u32)", 8))?; 415 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 416 let func = instance.get_func(&mut store, "echo").unwrap(); 417 418 let input_map = vec![(Val::U8(10), Val::U32(100)), (Val::U8(20), Val::U32(200))]; 419 let input = Val::Map(input_map); 420 421 func.call(&mut store, &[input.clone()], &mut output)?; 422 assert_eq!(input, output[0]); 423 424 // Test map<u16, u64> - key_size=2, value_align=8 425 // This would fail with the alignment bug because value would be at offset 2 instead of 8 426 let component = Component::new(&engine, make_echo_component("(map u16 u64)", 8))?; 427 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 428 let func = instance.get_func(&mut store, "echo").unwrap(); 429 430 let input_map = vec![ 431 (Val::U16(1), Val::U64(10000)), 432 (Val::U16(2), Val::U64(20000)), 433 ]; 434 let input = Val::Map(input_map); 435 436 func.call(&mut store, &[input.clone()], &mut output)?; 437 assert_eq!(input, output[0]); 438 439 Ok(()) 440 } 441 442 #[test] 443 fn maps_large() -> Result<()> { 444 let engine = super::map_engine(); 445 let mut store = Store::new(&engine, ()); 446 447 let component = Component::new(&engine, make_echo_component("(map u32 string)", 8))?; 448 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 449 let func = instance.get_func(&mut store, "echo").unwrap(); 450 451 // Create a map with many entries 452 let input_map: Vec<(Val, Val)> = (0..100) 453 .map(|i| (Val::U32(i), Val::String(format!("value_{i}")))) 454 .collect(); 455 let input = Val::Map(input_map); 456 457 let mut output = [Val::Bool(false)]; 458 func.call(&mut store, &[input.clone()], &mut output)?; 459 460 // Verify all entries are present 461 match &output[0] { 462 Val::Map(output_map) => { 463 assert_eq!(output_map.len(), 100); 464 for i in 0..100 { 465 assert!(output_map.iter().any(|(k, v)| { 466 *k == Val::U32(i) && *v == Val::String(format!("value_{i}")) 467 })); 468 } 469 } 470 _ => panic!("expected map"), 471 } 472 473 Ok(()) 474 } 475 476 #[test] 477 fn records() -> Result<()> { 478 let engine = super::engine(); 479 let mut store = Store::new(&engine, ()); 480 481 let component = Component::new( 482 &engine, 483 make_echo_component_with_params( 484 r#" 485 (type $c' (record 486 (field "D" bool) 487 (field "E" u32) 488 )) 489 (export $c "c" (type $c')) 490 (type $Foo' (record 491 (field "A" u32) 492 (field "B" float64) 493 (field "C" $c) 494 )) 495 "#, 496 &[ 497 Param(Type::I32, Some(0)), 498 Param(Type::F64, Some(8)), 499 Param(Type::U8, Some(16)), 500 Param(Type::I32, Some(20)), 501 ], 502 ), 503 )?; 504 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 505 let func = instance.get_func(&mut store, "echo").unwrap(); 506 let input = Val::Record(vec![ 507 ("A".into(), Val::U32(32343)), 508 ("B".into(), Val::Float64(3.14159265)), 509 ( 510 "C".into(), 511 Val::Record(vec![ 512 ("D".into(), Val::Bool(false)), 513 ("E".into(), Val::U32(2084037802)), 514 ]), 515 ), 516 ]); 517 let mut output = [Val::Bool(false)]; 518 func.call(&mut store, &[input.clone()], &mut output)?; 519 520 assert_eq!(input, output[0]); 521 522 // Sad path: type mismatch 523 524 let err = Val::Record(vec![ 525 ("A".into(), Val::S32(32343)), 526 ("B".into(), Val::Float64(3.14159265)), 527 ( 528 "C".into(), 529 Val::Record(vec![ 530 ("D".into(), Val::Bool(false)), 531 ("E".into(), Val::U32(2084037802)), 532 ]), 533 ), 534 ]); 535 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 536 let func = instance.get_func(&mut store, "echo").unwrap(); 537 let err = func.call(&mut store, &[err], &mut output).unwrap_err(); 538 assert!(err.to_string().contains("type mismatch"), "{err}"); 539 540 // Sad path: too many fields 541 542 let err = Val::Record(vec![ 543 ("A".into(), Val::U32(32343)), 544 ("B".into(), Val::Float64(3.14159265)), 545 ( 546 "C".into(), 547 Val::Record(vec![ 548 ("D".into(), Val::Bool(false)), 549 ("E".into(), Val::U32(2084037802)), 550 ]), 551 ), 552 ("F".into(), Val::Bool(true)), 553 ]); 554 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 555 let func = instance.get_func(&mut store, "echo").unwrap(); 556 let err = func.call(&mut store, &[err], &mut output).unwrap_err(); 557 assert!( 558 err.to_string().contains("expected 3 fields, got 4"), 559 "{err}" 560 ); 561 562 // Sad path: too few fields 563 564 let err = Val::Record(vec![ 565 ("A".into(), Val::U32(32343)), 566 ("B".into(), Val::Float64(3.14159265)), 567 ]); 568 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 569 let func = instance.get_func(&mut store, "echo").unwrap(); 570 let err = func.call(&mut store, &[err], &mut output).unwrap_err(); 571 assert!( 572 err.to_string().contains("expected 3 fields, got 2"), 573 "{err}" 574 ); 575 576 Ok(()) 577 } 578 579 #[test] 580 fn variants() -> Result<()> { 581 let engine = super::engine(); 582 let mut store = Store::new(&engine, ()); 583 584 let fragment = r#" 585 (type $c' (record (field "D" bool) (field "E" u32))) 586 (export $c "c" (type $c')) 587 (type $Foo' (variant 588 (case "A" u32) 589 (case "B" float64) 590 (case "C" $c) 591 )) 592 "#; 593 594 let component = Component::new( 595 &engine, 596 make_echo_component_with_params( 597 fragment, 598 &[ 599 Param(Type::U8, Some(0)), 600 Param(Type::I64, Some(8)), 601 Param(Type::I32, None), 602 ], 603 ), 604 )?; 605 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 606 let func = instance.get_func(&mut store, "echo").unwrap(); 607 let input = Val::Variant("B".into(), Some(Box::new(Val::Float64(3.14159265)))); 608 let mut output = [Val::Bool(false)]; 609 func.call(&mut store, &[input.clone()], &mut output)?; 610 611 assert_eq!(input, output[0]); 612 613 // Do it again, this time using case "C" 614 615 let component = Component::new( 616 &engine, 617 make_echo_component_with_params( 618 fragment, 619 &[ 620 Param(Type::U8, Some(0)), 621 Param(Type::I64, Some(8)), 622 Param(Type::I32, Some(12)), 623 ], 624 ), 625 )?; 626 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 627 let func = instance.get_func(&mut store, "echo").unwrap(); 628 let input = Val::Variant( 629 "C".into(), 630 Some(Box::new(Val::Record(vec![ 631 ("D".into(), Val::Bool(true)), 632 ("E".into(), Val::U32(314159265)), 633 ]))), 634 ); 635 func.call(&mut store, &[input.clone()], &mut output)?; 636 637 assert_eq!(input, output[0]); 638 639 // Sad path: type mismatch 640 641 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 642 let func = instance.get_func(&mut store, "echo").unwrap(); 643 let err = Val::Variant("B".into(), Some(Box::new(Val::U64(314159265)))); 644 let err = func.call(&mut store, &[err], &mut output).unwrap_err(); 645 assert!(err.to_string().contains("type mismatch"), "{err}"); 646 647 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 648 let func = instance.get_func(&mut store, "echo").unwrap(); 649 let err = Val::Variant("B".into(), None); 650 let err = func.call(&mut store, &[err], &mut output).unwrap_err(); 651 assert!( 652 err.to_string().contains("expected a payload for case `B`"), 653 "{err}" 654 ); 655 656 // Sad path: unknown case 657 658 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 659 let func = instance.get_func(&mut store, "echo").unwrap(); 660 let err = Val::Variant("D".into(), Some(Box::new(Val::U64(314159265)))); 661 let err = func.call(&mut store, &[err], &mut output).unwrap_err(); 662 assert!(err.to_string().contains("unknown variant case"), "{err}"); 663 664 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 665 let func = instance.get_func(&mut store, "echo").unwrap(); 666 let err = Val::Variant("D".into(), None); 667 let err = func.call(&mut store, &[err], &mut output).unwrap_err(); 668 assert!(err.to_string().contains("unknown variant case"), "{err}"); 669 670 // Make sure we lift variants which have cases of different sizes with the correct alignment 671 672 let component = Component::new( 673 &engine, 674 make_echo_component_with_params( 675 r#" 676 (type $c' (record (field "D" bool) (field "E" u32))) 677 (export $c "c" (type $c')) 678 (type $a' (variant 679 (case "A" u32) 680 (case "B" float64) 681 (case "C" $c) 682 )) 683 (export $a "a" (type $a')) 684 (type $Foo' (record 685 (field "A" $a) 686 (field "B" u32) 687 )) 688 "#, 689 &[ 690 Param(Type::U8, Some(0)), 691 Param(Type::I64, Some(8)), 692 Param(Type::I32, None), 693 Param(Type::I32, Some(16)), 694 ], 695 ), 696 )?; 697 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 698 let func = instance.get_func(&mut store, "echo").unwrap(); 699 let input = Val::Record(vec![ 700 ( 701 "A".into(), 702 Val::Variant("A".into(), Some(Box::new(Val::U32(314159265)))), 703 ), 704 ("B".into(), Val::U32(628318530)), 705 ]); 706 func.call(&mut store, &[input.clone()], &mut output)?; 707 708 assert_eq!(input, output[0]); 709 710 Ok(()) 711 } 712 713 #[test] 714 fn flags() -> Result<()> { 715 let engine = super::engine(); 716 let mut store = Store::new(&engine, ()); 717 718 let component = Component::new( 719 &engine, 720 make_echo_component_with_params( 721 r#"(flags "A" "B" "C" "D" "E")"#, 722 &[Param(Type::U8, Some(0))], 723 ), 724 )?; 725 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 726 let func = instance.get_func(&mut store, "echo").unwrap(); 727 let input = Val::Flags(vec!["B".into(), "D".into()]); 728 let mut output = [Val::Bool(false)]; 729 func.call(&mut store, &[input.clone()], &mut output)?; 730 731 assert_eq!(input, output[0]); 732 733 // Sad path: unknown flags 734 735 let err = Val::Flags(vec!["B".into(), "D".into(), "F".into()]); 736 let err = func.call(&mut store, &[err], &mut output).unwrap_err(); 737 assert!(err.to_string().contains("unknown flag"), "{err}"); 738 739 Ok(()) 740 } 741 742 #[test] 743 fn everything() -> Result<()> { 744 // This serves to test both nested types and storing parameters on the heap (i.e. exceeding `MAX_STACK_PARAMS`) 745 746 let engine = super::engine(); 747 let mut store = Store::new(&engine, ()); 748 749 let component = Component::new( 750 &engine, 751 make_echo_component_with_params( 752 r#" 753 (type $b' (enum "a" "b")) 754 (export $b "b" (type $b')) 755 (type $c' (record (field "D" bool) (field "E" u32))) 756 (export $c "c" (type $c')) 757 (type $f' (flags "G" "H" "I")) 758 (export $f "f" (type $f')) 759 (type $m' (record (field "N" bool) (field "O" u32))) 760 (export $m "m" (type $m')) 761 (type $j' (variant 762 (case "K" u32) 763 (case "L" float64) 764 (case "M" $m) 765 )) 766 (export $j "j" (type $j')) 767 768 (type $Foo' (record 769 (field "A" u32) 770 (field "B" $b) 771 (field "C" $c) 772 (field "F" (list $f)) 773 (field "J" $j) 774 (field "P" s8) 775 (field "Q" s16) 776 (field "R" s32) 777 (field "S" s64) 778 (field "T" float32) 779 (field "U" float64) 780 (field "V" string) 781 (field "W" char) 782 (field "Y" (tuple u32 u32)) 783 (field "AA" (option u32)) 784 (field "BB" (result string (error string))) 785 )) 786 "#, 787 &[ 788 Param(Type::I32, Some(0)), 789 Param(Type::U8, Some(4)), 790 Param(Type::U8, Some(5)), 791 Param(Type::I32, Some(8)), 792 Param(Type::I32, Some(12)), 793 Param(Type::I32, Some(16)), 794 Param(Type::U8, Some(20)), 795 Param(Type::I64, Some(28)), 796 Param(Type::I32, Some(32)), 797 Param(Type::S8, Some(36)), 798 Param(Type::S16, Some(38)), 799 Param(Type::I32, Some(40)), 800 Param(Type::I64, Some(48)), 801 Param(Type::F32, Some(56)), 802 Param(Type::F64, Some(64)), 803 Param(Type::I32, Some(72)), 804 Param(Type::I32, Some(76)), 805 Param(Type::I32, Some(80)), 806 Param(Type::I32, Some(84)), 807 Param(Type::I32, Some(88)), 808 Param(Type::I64, Some(96)), 809 Param(Type::U8, Some(104)), 810 Param(Type::I32, Some(108)), 811 Param(Type::U8, Some(112)), 812 Param(Type::I32, Some(116)), 813 Param(Type::I32, Some(120)), 814 ], 815 ), 816 )?; 817 let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 818 let func = instance.get_func(&mut store, "echo").unwrap(); 819 let input = Val::Record(vec![ 820 ("A".into(), Val::U32(32343)), 821 ("B".into(), Val::Enum("b".to_string())), 822 ( 823 "C".into(), 824 Val::Record(vec![ 825 ("D".to_string(), Val::Bool(false)), 826 ("E".to_string(), Val::U32(2084037802)), 827 ]), 828 ), 829 ( 830 "F".into(), 831 Val::List(vec![Val::Flags(vec!["G".to_string(), "I".to_string()])]), 832 ), 833 ( 834 "J".into(), 835 Val::Variant("L".to_string(), Some(Box::new(Val::Float64(3.14159265)))), 836 ), 837 ("P".into(), Val::S8(42)), 838 ("Q".into(), Val::S16(4242)), 839 ("R".into(), Val::S32(42424242)), 840 ("S".into(), Val::S64(424242424242424242)), 841 ("T".into(), Val::Float32(3.14159265)), 842 ("U".into(), Val::Float64(3.14159265)), 843 ("V".into(), Val::String("wow, nice types".to_string())), 844 ("W".into(), Val::Char('')), 845 ("Y".into(), Val::Tuple(vec![Val::U32(42), Val::U32(24)])), 846 ( 847 "AA".into(), 848 Val::Option(Some(Box::new(Val::U32(314159265)))), 849 ), 850 ( 851 "BB".into(), 852 Val::Result(Ok(Some(Box::new(Val::String("no problem".to_string()))))), 853 ), 854 ]); 855 let mut output = [Val::Bool(false)]; 856 func.call(&mut store, &[input.clone()], &mut output)?; 857 858 assert_eq!(input, output[0]); 859 860 Ok(()) 861 } 862 863 #[test] 864 fn introspection() -> Result<()> { 865 let engine = super::engine(); 866 867 let component = Component::new( 868 &engine, 869 format!( 870 r#" 871 (component 872 (import "res" (type $res (sub resource))) 873 874 (import "ai" (instance $i)) 875 (import "bi" (instance $i2 (export "m" (core module)))) 876 877 (alias export $i2 "m" (core module $m)) 878 879 (type $t (func (param "a" u32) (result u32))) 880 (component $a 881 (core module $m 882 (func (export "add-five") (param i32) (result i32) 883 local.get 0 884 i32.const 5 885 i32.add) 886 ) 887 (core instance $m (instantiate $m)) 888 (func (export "add-five") (type $t) (canon lift (core func $m "add-five"))) 889 ) 890 (component $b 891 (import "interface-v1" (instance $i 892 (export "add-five" (func (type $t))))) 893 (core module $m 894 (func $add-five (import "interface-0.1.0" "add-five") (param i32) (result i32)) 895 (func) ;; causes index out of bounds 896 (func (export "run") (result i32) i32.const 0 call $add-five) 897 ) 898 (core func $add-five (canon lower (func $i "add-five"))) 899 (core instance $i (instantiate 0 900 (with "interface-0.1.0" (instance 901 (export "add-five" (func $add-five)) 902 )) 903 )) 904 (func (result u32) (canon lift (core func $i "run"))) 905 (export "run" (func 1)) 906 ) 907 (instance $a (instantiate $a)) 908 (instance $b (instantiate $b (with "interface-v1" (instance $a)))) 909 (export "run" (func $b "run")) 910 911 (component $c 912 (component $c 913 (export "m" (core module $m)) 914 ) 915 (instance $c (instantiate $c)) 916 (export "i" (instance $c)) 917 ) 918 (instance $c (instantiate $c)) 919 (export "i" (instance $c)) 920 (export "r" (instance $i)) 921 (export "r2" (instance $i2)) 922 923 (type $b' (enum "a" "b")) 924 (export $b "b" (type $b')) 925 (type $c' (record (field "D" bool) (field "E" u32))) 926 (export $c "c" (type $c')) 927 (type $f' (flags "G" "H" "I")) 928 (export $f "f" (type $f')) 929 (type $m' (record (field "N" bool) (field "O" u32))) 930 (export $m "m" (type $m')) 931 (type $j' (variant 932 (case "K" u32) 933 (case "L" float64) 934 (case "M" $m) 935 )) 936 (export $j "j" (type $j')) 937 938 (type $Foo' (record 939 (field "A" u32) 940 (field "B" $b) 941 (field "C" $c) 942 (field "F" (list $f)) 943 (field "J" $j) 944 (field "P" s8) 945 (field "Q" s16) 946 (field "R" s32) 947 (field "S" s64) 948 (field "T" float32) 949 (field "U" float64) 950 (field "V" string) 951 (field "W" char) 952 (field "Y" (tuple u32 u32)) 953 (field "AA" (option u32)) 954 (field "BB" (result string (error string))) 955 (field "CC" (own $res)) 956 )) 957 (export $Foo "foo" (type $Foo')) 958 959 (core module $m2 960 (func (export "f") (param i32) (result i32) 961 local.get 0 962 ) 963 (memory (export "memory") 1) 964 {REALLOC_AND_FREE} 965 ) 966 (core instance $i3 (instantiate $m2)) 967 968 (func (export "fn") (param "x" (option $Foo)) (result (option (tuple u32 u32))) 969 (canon lift 970 (core func $i3 "f") 971 (memory $i3 "memory") 972 (realloc (func $i3 "realloc")) 973 ) 974 ) 975 ) 976 "# 977 ), 978 )?; 979 980 struct MyType; 981 982 let mut linker = Linker::<()>::new(&engine); 983 linker 984 .root() 985 .resource("res", ResourceType::host::<MyType>(), |_, _| Ok(()))?; 986 linker.instance("ai")?; 987 linker 988 .instance("bi")? 989 .module("m", &Module::new(&engine, "(module)")?)?; 990 991 let component_ty = linker.substituted_component_type(&component)?; 992 993 let mut imports = component_ty.imports(linker.engine()); 994 assert_eq!(imports.len(), 3); 995 let (name, res_ty) = imports.next().unwrap(); 996 assert_eq!(name, "res"); 997 let ComponentItem::Resource(res_ty) = res_ty else { 998 panic!("`res` import item of wrong type") 999 }; 1000 assert_eq!(res_ty, ResourceType::host::<MyType>()); 1001 1002 let (name, ai_ty) = imports.next().unwrap(); 1003 assert_eq!(name, "ai"); 1004 let ComponentItem::ComponentInstance(ai_ty) = ai_ty else { 1005 panic!("`ai` import item of wrong type") 1006 }; 1007 assert_eq!(ai_ty.exports(linker.engine()).len(), 0); 1008 1009 let (name, bi_ty) = imports.next().unwrap(); 1010 assert_eq!(name, "bi"); 1011 let ComponentItem::ComponentInstance(bi_ty) = bi_ty else { 1012 panic!("`bi` import item of wrong type") 1013 }; 1014 let mut bi_exports = bi_ty.exports(linker.engine()); 1015 assert_eq!(bi_exports.len(), 1); 1016 let (name, bi_m_ty) = bi_exports.next().unwrap(); 1017 assert_eq!(name, "m"); 1018 let ComponentItem::Module(bi_m_ty) = bi_m_ty else { 1019 panic!("`bi.m` import item of wrong type") 1020 }; 1021 assert_eq!(bi_m_ty.imports(linker.engine()).len(), 0); 1022 assert_eq!(bi_m_ty.exports(linker.engine()).len(), 0); 1023 1024 let mut exports = component_ty.exports(linker.engine()); 1025 assert_eq!(exports.len(), 11); 1026 1027 let (name, run_ty) = exports.next().unwrap(); 1028 assert_eq!(name, "run"); 1029 let ComponentItem::ComponentFunc(run_ty) = run_ty else { 1030 panic!("`run` export item of wrong type") 1031 }; 1032 assert_eq!(run_ty.params().len(), 0); 1033 1034 let mut run_results = run_ty.results(); 1035 assert_eq!(run_results.len(), 1); 1036 assert_eq!(run_results.next().unwrap(), types::Type::U32); 1037 1038 let (name, i_ty) = exports.next().unwrap(); 1039 assert_eq!(name, "i"); 1040 let ComponentItem::ComponentInstance(i_ty) = i_ty else { 1041 panic!("`i` export item of wrong type") 1042 }; 1043 let mut i_ty_exports = i_ty.exports(linker.engine()); 1044 assert_eq!(i_ty_exports.len(), 1); 1045 let (name, i_i_ty) = i_ty_exports.next().unwrap(); 1046 assert_eq!(name, "i"); 1047 let ComponentItem::ComponentInstance(i_i_ty) = i_i_ty else { 1048 panic!("`i.i` import item of wrong type") 1049 }; 1050 let mut i_i_ty_exports = i_i_ty.exports(linker.engine()); 1051 assert_eq!(i_i_ty_exports.len(), 1); 1052 let (name, i_i_m_ty) = i_i_ty_exports.next().unwrap(); 1053 assert_eq!(name, "m"); 1054 let ComponentItem::Module(i_i_m_ty) = i_i_m_ty else { 1055 panic!("`i.i.m` import item of wrong type") 1056 }; 1057 assert_eq!(i_i_m_ty.imports(linker.engine()).len(), 0); 1058 assert_eq!(i_i_m_ty.exports(linker.engine()).len(), 0); 1059 1060 let (name, r_ty) = exports.next().unwrap(); 1061 assert_eq!(name, "r"); 1062 let ComponentItem::ComponentInstance(r_ty) = r_ty else { 1063 panic!("`r` export item of wrong type") 1064 }; 1065 assert_eq!(r_ty.exports(linker.engine()).len(), 0); 1066 1067 let (name, r2_ty) = exports.next().unwrap(); 1068 assert_eq!(name, "r2"); 1069 let ComponentItem::ComponentInstance(r2_ty) = r2_ty else { 1070 panic!("`r2` export item of wrong type") 1071 }; 1072 let mut r2_exports = r2_ty.exports(linker.engine()); 1073 assert_eq!(r2_exports.len(), 1); 1074 let (name, r2_m_ty) = r2_exports.next().unwrap(); 1075 assert_eq!(name, "m"); 1076 let ComponentItem::Module(r2_m_ty) = r2_m_ty else { 1077 panic!("`r2.m` export item of wrong type") 1078 }; 1079 assert_eq!(r2_m_ty.imports(linker.engine()).len(), 0); 1080 assert_eq!(r2_m_ty.exports(linker.engine()).len(), 0); 1081 1082 let (name, b_ty) = exports.next().unwrap(); 1083 assert_eq!(name, "b"); 1084 let ComponentItem::Type(b_ty) = b_ty else { 1085 panic!("`b` export item of wrong type") 1086 }; 1087 assert_eq!(b_ty.unwrap_enum().names().collect::<Vec<_>>(), ["a", "b"]); 1088 1089 let (name, c_ty) = exports.next().unwrap(); 1090 assert_eq!(name, "c"); 1091 let ComponentItem::Type(c_ty) = c_ty else { 1092 panic!("`c` export item of wrong type") 1093 }; 1094 let mut fields = c_ty.unwrap_record().fields(); 1095 { 1096 let Field { name, ty } = fields.next().unwrap(); 1097 assert_eq!(name, "D"); 1098 assert_eq!(ty, types::Type::Bool); 1099 let Field { name, ty } = fields.next().unwrap(); 1100 assert_eq!(name, "E"); 1101 assert_eq!(ty, types::Type::U32); 1102 } 1103 1104 let (name, f_ty) = exports.next().unwrap(); 1105 assert_eq!(name, "f"); 1106 let ComponentItem::Type(f_ty) = f_ty else { 1107 panic!("`f` export item of wrong type") 1108 }; 1109 assert_eq!( 1110 f_ty.unwrap_flags().names().collect::<Vec<_>>(), 1111 ["G", "H", "I"] 1112 ); 1113 1114 let (name, m_ty) = exports.next().unwrap(); 1115 assert_eq!(name, "m"); 1116 let ComponentItem::Type(m_ty) = m_ty else { 1117 panic!("`m` export item of wrong type") 1118 }; 1119 { 1120 let mut fields = m_ty.unwrap_record().fields(); 1121 let Field { name, ty } = fields.next().unwrap(); 1122 assert_eq!(name, "N"); 1123 assert_eq!(ty, types::Type::Bool); 1124 let Field { name, ty } = fields.next().unwrap(); 1125 assert_eq!(name, "O"); 1126 assert_eq!(ty, types::Type::U32); 1127 } 1128 1129 let (name, j_ty) = exports.next().unwrap(); 1130 assert_eq!(name, "j"); 1131 let ComponentItem::Type(j_ty) = j_ty else { 1132 panic!("`j` export item of wrong type") 1133 }; 1134 let mut cases = j_ty.unwrap_variant().cases(); 1135 { 1136 let Case { name, ty } = cases.next().unwrap(); 1137 assert_eq!(name, "K"); 1138 assert_eq!(ty, Some(types::Type::U32)); 1139 let Case { name, ty } = cases.next().unwrap(); 1140 assert_eq!(name, "L"); 1141 assert_eq!(ty, Some(types::Type::Float64)); 1142 let Case { name, ty } = cases.next().unwrap(); 1143 assert_eq!(name, "M"); 1144 assert_eq!(ty, Some(m_ty)); 1145 } 1146 1147 let (name, foo_ty) = exports.next().unwrap(); 1148 assert_eq!(name, "foo"); 1149 let ComponentItem::Type(foo_ty) = foo_ty else { 1150 panic!("`foo` export item of wrong type") 1151 }; 1152 { 1153 let mut fields = foo_ty.unwrap_record().fields(); 1154 assert_eq!(fields.len(), 17); 1155 let Field { name, ty } = fields.next().unwrap(); 1156 assert_eq!(name, "A"); 1157 assert_eq!(ty, types::Type::U32); 1158 let Field { name, ty } = fields.next().unwrap(); 1159 assert_eq!(name, "B"); 1160 assert_eq!(ty, b_ty); 1161 let Field { name, ty } = fields.next().unwrap(); 1162 assert_eq!(name, "C"); 1163 assert_eq!(ty, c_ty); 1164 let Field { name, ty } = fields.next().unwrap(); 1165 assert_eq!(name, "F"); 1166 let ty = ty.unwrap_list(); 1167 assert_eq!(ty.ty(), f_ty); 1168 let Field { name, ty } = fields.next().unwrap(); 1169 assert_eq!(name, "J"); 1170 assert_eq!(ty, j_ty); 1171 let Field { name, ty } = fields.next().unwrap(); 1172 assert_eq!(name, "P"); 1173 assert_eq!(ty, types::Type::S8); 1174 let Field { name, ty } = fields.next().unwrap(); 1175 assert_eq!(name, "Q"); 1176 assert_eq!(ty, types::Type::S16); 1177 let Field { name, ty } = fields.next().unwrap(); 1178 assert_eq!(name, "R"); 1179 assert_eq!(ty, types::Type::S32); 1180 let Field { name, ty } = fields.next().unwrap(); 1181 assert_eq!(name, "S"); 1182 assert_eq!(ty, types::Type::S64); 1183 let Field { name, ty } = fields.next().unwrap(); 1184 assert_eq!(name, "T"); 1185 assert_eq!(ty, types::Type::Float32); 1186 let Field { name, ty } = fields.next().unwrap(); 1187 assert_eq!(name, "U"); 1188 assert_eq!(ty, types::Type::Float64); 1189 let Field { name, ty } = fields.next().unwrap(); 1190 assert_eq!(name, "V"); 1191 assert_eq!(ty, types::Type::String); 1192 let Field { name, ty } = fields.next().unwrap(); 1193 assert_eq!(name, "W"); 1194 assert_eq!(ty, types::Type::Char); 1195 let Field { name, ty } = fields.next().unwrap(); 1196 assert_eq!(name, "Y"); 1197 assert_eq!( 1198 ty.unwrap_tuple().types().collect::<Vec<_>>(), 1199 [types::Type::U32, types::Type::U32] 1200 ); 1201 let Field { name, ty } = fields.next().unwrap(); 1202 assert_eq!(name, "AA"); 1203 assert_eq!(ty.unwrap_option().ty(), types::Type::U32); 1204 let Field { name, ty } = fields.next().unwrap(); 1205 assert_eq!(name, "BB"); 1206 let ty = ty.unwrap_result(); 1207 assert_eq!(ty.ok(), Some(types::Type::String)); 1208 assert_eq!(ty.err(), Some(types::Type::String)); 1209 let Field { name, ty } = fields.next().unwrap(); 1210 assert_eq!(name, "CC"); 1211 assert_eq!(*ty.unwrap_own(), res_ty); 1212 } 1213 1214 let (name, fn_ty) = exports.next().unwrap(); 1215 assert_eq!(name, "fn"); 1216 let ComponentItem::ComponentFunc(fn_ty) = fn_ty else { 1217 panic!("`fn` export item of wrong type") 1218 }; 1219 let mut params = fn_ty.params(); 1220 assert_eq!(params.len(), 1); 1221 let (name, param) = params.next().unwrap(); 1222 assert_eq!(name, "x"); 1223 assert_eq!(param.unwrap_option().ty(), foo_ty); 1224 1225 let mut results = fn_ty.results(); 1226 assert_eq!(results.len(), 1); 1227 assert_eq!( 1228 results 1229 .next() 1230 .unwrap() 1231 .unwrap_option() 1232 .ty() 1233 .unwrap_tuple() 1234 .types() 1235 .collect::<Vec<_>>(), 1236 [types::Type::U32, types::Type::U32] 1237 ); 1238 Ok(()) 1239 } 1240