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