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