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