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