1 #![allow(dead_code, reason = "lots of macro-generated code")] 2 3 macro_rules! gentest { 4 ($id:ident $name:tt $path:tt) => { 5 mod $id { 6 mod sugar { 7 wasmtime::component::bindgen!(in $path); 8 } 9 mod async_ { 10 wasmtime::component::bindgen!({ 11 path: $path, 12 imports: { default: async }, 13 exports: { default: async }, 14 }); 15 } 16 mod concurrent { 17 wasmtime::component::bindgen!({ 18 path: $path, 19 imports: { default: async | store }, 20 exports: { default: async | store }, 21 }); 22 } 23 mod tracing { 24 wasmtime::component::bindgen!({ 25 path: $path, 26 imports: { default: tracing | verbose_tracing }, 27 exports: { default: tracing | verbose_tracing }, 28 ownership: Borrowing { 29 duplicate_if_necessary: true 30 } 31 }); 32 } 33 mod imports_with_store { 34 wasmtime::component::bindgen!({ 35 path: $path, 36 imports: { default: store }, 37 }); 38 } 39 } 40 }; 41 } 42 43 component_macro_test_helpers::foreach!(gentest); 44 45 mod with_key_and_resources { 46 use wasmtime::Result; 47 use wasmtime::component::Resource; 48 49 wasmtime::component::bindgen!({ 50 inline: " 51 package demo:pkg; 52 53 interface bar { 54 resource a; 55 resource b; 56 } 57 58 world foo { 59 resource a; 60 resource b; 61 62 import foo: interface { 63 resource a; 64 resource b; 65 } 66 67 import bar; 68 } 69 ", 70 with: { 71 "a": MyA, 72 "b": MyA, 73 "foo.a": MyA, 74 "foo.b": MyA, 75 "demo:pkg/bar.a": MyA, 76 "demo:pkg/bar.b": MyA, 77 }, 78 }); 79 80 pub struct MyA; 81 82 struct MyComponent; 83 84 impl FooImports for MyComponent {} 85 86 impl HostA for MyComponent { 87 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 88 loop {} 89 } 90 } 91 92 impl HostB for MyComponent { 93 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 94 loop {} 95 } 96 } 97 98 impl foo::Host for MyComponent {} 99 100 impl foo::HostA for MyComponent { 101 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 102 loop {} 103 } 104 } 105 106 impl foo::HostB for MyComponent { 107 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 108 loop {} 109 } 110 } 111 112 impl demo::pkg::bar::Host for MyComponent {} 113 114 impl demo::pkg::bar::HostA for MyComponent { 115 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 116 loop {} 117 } 118 } 119 120 impl demo::pkg::bar::HostB for MyComponent { 121 fn drop(&mut self, _: Resource<MyA>) -> Result<()> { 122 loop {} 123 } 124 } 125 } 126 127 mod trappable_errors_with_versioned_and_unversioned_packages { 128 wasmtime::component::bindgen!({ 129 world: "foo:foo/nope", 130 inline: " 131 package foo:[email protected]; 132 133 interface a { 134 variant error { 135 other(string), 136 } 137 138 f: func() -> result<_, error>; 139 } 140 141 world foo { 142 import a; 143 } 144 ", 145 path: "tests/codegen/unversioned-foo.wit", 146 trappable_error_type: { 147 "foo:foo/[email protected]" => MyX, 148 }, 149 }); 150 151 type MyX = u64; 152 } 153 154 mod trappable_errors { 155 wasmtime::component::bindgen!({ 156 inline: " 157 package demo:pkg; 158 159 interface a { 160 type b = u64; 161 162 z1: func() -> result<_, b>; 163 z2: func() -> result<_, b>; 164 } 165 166 interface b { 167 use a.{b}; 168 z: func() -> result<_, b>; 169 } 170 171 interface c { 172 type b = u64; 173 } 174 175 interface d { 176 use c.{b}; 177 z: func() -> result<_, b>; 178 } 179 180 world foo { 181 import a; 182 import b; 183 import d; 184 } 185 ", 186 trappable_error_type: { 187 "demo:pkg/a.b" => MyX, 188 "demo:pkg/c.b" => MyX, 189 }, 190 }); 191 192 type MyX = u32; 193 } 194 195 mod interface_name_with_rust_keyword { 196 wasmtime::component::bindgen!({ 197 inline: " 198 package foo:foo; 199 200 interface crate { } 201 202 world foo { 203 export crate; 204 } 205 " 206 }); 207 } 208 209 mod with_works_with_hierarchy { 210 mod bindings { 211 wasmtime::component::bindgen!({ 212 inline: " 213 package foo:foo; 214 215 interface a { 216 record t { 217 x: u32, 218 } 219 x: func() -> t; 220 } 221 222 interface b { 223 use a.{t}; 224 x: func() -> t; 225 } 226 227 interface c { 228 use b.{t}; 229 x: func() -> t; 230 } 231 232 world foo { 233 import c; 234 } 235 " 236 }); 237 } 238 239 mod with_just_one_interface { 240 wasmtime::component::bindgen!({ 241 inline: " 242 package foo:foo; 243 244 interface a { 245 record t { 246 x: u32, 247 } 248 x: func() -> t; 249 } 250 251 interface b { 252 use a.{t}; 253 x: func() -> t; 254 } 255 256 interface c { 257 use b.{t}; 258 x: func() -> t; 259 } 260 261 world foo { 262 use c.{t}; 263 264 import x: func() -> t; 265 } 266 ", 267 with: { "foo:foo/a": super::bindings::foo::foo::a } 268 }); 269 270 struct X; 271 272 impl FooImports for X { 273 fn x(&mut self) -> super::bindings::foo::foo::a::T { 274 loop {} 275 } 276 } 277 } 278 279 mod with_whole_package { 280 wasmtime::component::bindgen!({ 281 inline: " 282 package foo:foo; 283 284 interface a { 285 record t { 286 x: u32, 287 } 288 x: func() -> t; 289 } 290 291 interface b { 292 use a.{t}; 293 x: func() -> t; 294 } 295 296 interface c { 297 use b.{t}; 298 x: func() -> t; 299 } 300 301 world foo { 302 use c.{t}; 303 304 import x: func() -> t; 305 } 306 ", 307 with: { "foo:foo": super::bindings::foo::foo } 308 }); 309 310 struct X; 311 312 impl FooImports for X { 313 fn x(&mut self) -> super::bindings::foo::foo::a::T { 314 loop {} 315 } 316 } 317 } 318 319 mod with_whole_namespace { 320 wasmtime::component::bindgen!({ 321 inline: " 322 package foo:foo; 323 324 interface a { 325 record t { 326 x: u32, 327 } 328 x: func() -> t; 329 } 330 331 interface b { 332 use a.{t}; 333 x: func() -> t; 334 } 335 336 interface c { 337 use b.{t}; 338 x: func() -> t; 339 } 340 341 world foo { 342 use c.{t}; 343 344 import x: func() -> t; 345 } 346 ", 347 with: { "foo": super::bindings::foo } 348 }); 349 350 struct X; 351 352 impl FooImports for X { 353 fn x(&mut self) -> super::bindings::foo::foo::a::T { 354 loop {} 355 } 356 } 357 } 358 } 359 360 mod trappable_imports { 361 mod none { 362 wasmtime::component::bindgen!({ 363 inline: " 364 package foo:foo; 365 366 world foo { 367 import foo: func(); 368 } 369 ", 370 }); 371 struct X; 372 373 impl FooImports for X { 374 fn foo(&mut self) {} 375 } 376 } 377 378 mod all { 379 wasmtime::component::bindgen!({ 380 inline: " 381 package foo:foo; 382 383 world foo { 384 import foo: func(); 385 } 386 ", 387 imports: { default: trappable }, 388 }); 389 struct X; 390 391 impl FooImports for X { 392 fn foo(&mut self) -> wasmtime::Result<()> { 393 Ok(()) 394 } 395 } 396 } 397 398 mod some { 399 wasmtime::component::bindgen!({ 400 inline: " 401 package foo:foo; 402 403 world foo { 404 import foo: func(); 405 import bar: func(); 406 } 407 ", 408 imports: { "foo": trappable }, 409 }); 410 struct X; 411 412 impl FooImports for X { 413 fn foo(&mut self) -> wasmtime::Result<()> { 414 Ok(()) 415 } 416 fn bar(&mut self) {} 417 } 418 } 419 420 mod across_interfaces { 421 use wasmtime::component::Resource; 422 423 wasmtime::component::bindgen!({ 424 inline: " 425 package foo:foo; 426 427 interface a { 428 foo: func(); 429 bar: func(); 430 431 resource r { 432 constructor(); 433 foo: func(); 434 bar: static func(); 435 } 436 } 437 438 world foo { 439 import a; 440 import foo: func(); 441 import bar: func(); 442 import i: interface { 443 foo: func(); 444 bar: func(); 445 } 446 447 } 448 ", 449 imports: { 450 "foo": trappable | exact, 451 "i.foo": trappable, 452 "foo:foo/a.foo": trappable, 453 }, 454 with: { "foo:foo/a.r": R }, 455 }); 456 457 struct X; 458 pub struct R; 459 460 impl FooImports for X { 461 fn foo(&mut self) -> wasmtime::Result<()> { 462 Ok(()) 463 } 464 fn bar(&mut self) {} 465 } 466 467 impl i::Host for X { 468 fn foo(&mut self) -> wasmtime::Result<()> { 469 Ok(()) 470 } 471 fn bar(&mut self) {} 472 } 473 474 impl foo::foo::a::Host for X { 475 fn foo(&mut self) -> wasmtime::Result<()> { 476 Ok(()) 477 } 478 fn bar(&mut self) {} 479 } 480 481 impl foo::foo::a::HostR for X { 482 fn new(&mut self) -> Resource<R> { 483 loop {} 484 } 485 fn foo(&mut self, _: Resource<R>) {} 486 fn bar(&mut self) {} 487 fn drop(&mut self, _: Resource<R>) -> wasmtime::Result<()> { 488 Ok(()) 489 } 490 } 491 } 492 493 mod resources { 494 use wasmtime::component::Resource; 495 496 wasmtime::component::bindgen!({ 497 inline: " 498 package foo:foo; 499 500 interface a { 501 resource r { 502 constructor(); 503 foo: func(); 504 bar: static func(); 505 } 506 } 507 508 world foo { 509 import a; 510 511 } 512 ", 513 imports: { 514 "foo:foo/a.[constructor]r": trappable, 515 "foo:foo/a.[method]r.foo": trappable, 516 "foo:foo/a.[static]r.bar": trappable, 517 }, 518 with: { "foo:foo/a.r": R }, 519 }); 520 521 struct X; 522 pub struct R; 523 524 impl foo::foo::a::Host for X {} 525 526 impl foo::foo::a::HostR for X { 527 fn new(&mut self) -> wasmtime::Result<Resource<R>> { 528 loop {} 529 } 530 fn foo(&mut self, _: Resource<R>) -> wasmtime::Result<()> { 531 Ok(()) 532 } 533 fn bar(&mut self) -> wasmtime::Result<()> { 534 Ok(()) 535 } 536 fn drop(&mut self, _: Resource<R>) -> wasmtime::Result<()> { 537 Ok(()) 538 } 539 } 540 } 541 } 542 543 mod custom_derives { 544 use std::collections::{HashSet, hash_map::RandomState}; 545 546 wasmtime::component::bindgen!({ 547 inline: " 548 package my:inline; 549 550 interface blah { 551 variant abc { 552 a, 553 b, 554 c 555 } 556 557 record foo { 558 field1: string, 559 field2: list<u32>, 560 field3: abc 561 } 562 563 bar: func(cool: foo); 564 } 565 566 world baz { 567 import blah; 568 } 569 ", 570 // Clone is included by default almost everywhere, so include it here to make sure it 571 // doesn't conflict 572 additional_derives: [serde::Serialize, serde::Deserialize, Hash, Clone, PartialEq, Eq], 573 }); 574 575 use my::inline::blah::{Abc, Foo, Host}; 576 577 struct X; 578 579 impl Host for X { 580 fn bar(&mut self, cool: Foo) { 581 // Check that built in derives that I've added actually work by seeing that this hashes 582 let _blah: HashSet<Foo, RandomState> = HashSet::from_iter([Foo { 583 field1: "hello".to_string(), 584 field2: vec![1, 2, 3], 585 field3: Abc::B, 586 }]); 587 588 // Check that the attributes from an external crate actually work. If they don't work, 589 // compilation will fail here 590 let _ = serde_json::to_string(&cool); 591 } 592 } 593 } 594 595 mod with_and_mixing_async { 596 mod with_async { 597 wasmtime::component::bindgen!({ 598 inline: " 599 package my:inline; 600 interface foo { 601 type t = u32; 602 foo: func() -> t; 603 } 604 interface bar { 605 use foo.{t}; 606 bar: func() -> t; 607 } 608 world x { 609 import bar; 610 } 611 ", 612 imports: { 613 "my:inline/bar.bar": async, 614 }, 615 }); 616 } 617 618 mod without_async { 619 wasmtime::component::bindgen!({ 620 inline: " 621 package my:inline; 622 interface foo { 623 type t = u32; 624 foo: func() -> t; 625 } 626 interface bar { 627 use foo.{t}; 628 bar: func() -> t; 629 } 630 world x { 631 import bar; 632 } 633 ", 634 with: { 635 "my:inline/foo": super::with_async::my::inline::foo, 636 }, 637 require_store_data_send: true, 638 }); 639 } 640 641 mod third { 642 wasmtime::component::bindgen!({ 643 inline: " 644 package my:inline; 645 interface foo { 646 type t = u32; 647 foo: func() -> t; 648 } 649 interface bar { 650 use foo.{t}; 651 bar: func() -> t; 652 } 653 interface baz { 654 use bar.{t}; 655 baz: func() -> t; 656 } 657 world x { 658 import baz; 659 } 660 ", 661 with: { 662 "my:inline/foo": super::with_async::my::inline::foo, 663 "my:inline/bar": super::without_async::my::inline::bar, 664 }, 665 require_store_data_send: true, 666 }); 667 } 668 } 669 670 mod trappable_error_type_and_versions { 671 struct MyError; 672 673 mod package_no_version_path_no_version { 674 wasmtime::component::bindgen!({ 675 inline: " 676 package my:inline; 677 interface i { 678 enum e { a, b, c } 679 } 680 world foo {} 681 ", 682 trappable_error_type: { 683 "my:inline/i.e" => super::MyError, 684 }, 685 }); 686 } 687 mod package_version_path_no_version { 688 wasmtime::component::bindgen!({ 689 inline: " 690 package my:[email protected]; 691 interface i { 692 enum e { a, b, c } 693 } 694 world foo {} 695 ", 696 trappable_error_type: { 697 "my:inline/i.e" => super::MyError, 698 }, 699 }); 700 } 701 mod package_version_path_version { 702 wasmtime::component::bindgen!({ 703 inline: " 704 package my:[email protected]; 705 interface i { 706 enum e { a, b, c } 707 } 708 world foo {} 709 ", 710 trappable_error_type: { 711 "my:inline/[email protected]" => super::MyError, 712 }, 713 }); 714 } 715 } 716 717 mod paths { 718 mod multiple_paths { 719 wasmtime::component::bindgen!({ 720 world: "test:paths/test", 721 inline: r#" 722 package test:paths; 723 world test { 724 import paths:path1/test; 725 export paths:path2/test; 726 } 727 "#, 728 path: ["tests/codegen/path1", "tests/codegen/path2"], 729 }); 730 } 731 } 732 733 mod import_async_interface { 734 pub mod async_interface_implementation { 735 wasmtime::component::bindgen!({ 736 world: "test:async-import/blah-impl", 737 inline: r#" 738 package test:async-import; 739 740 interface blah { 741 foo: func(); 742 } 743 744 world blah-impl { 745 import blah; 746 } 747 748 world bar { 749 import blah; 750 } 751 "#, 752 imports: { default: async }, 753 }); 754 755 use test::async_import::blah::Host; 756 struct X; 757 758 impl Host for X { 759 async fn foo(&mut self) {} 760 } 761 } 762 763 mod require_t_send { 764 wasmtime::component::bindgen!({ 765 world: "test:async-import/bar", 766 inline: r#" 767 package test:async-import; 768 769 interface blah { 770 foo: func(); 771 } 772 773 world blah-impl { 774 import blah; 775 } 776 777 world bar { 778 import blah; 779 } 780 "#, 781 with: { 782 "test:async-import/blah": super::async_interface_implementation::test::async_import::blah, 783 }, 784 imports: { default: async }, 785 }); 786 } 787 } 788