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