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