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