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