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         }
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         });
365         struct X;
366 
367         impl FooImports for X {
368             fn foo(&mut self) {}
369         }
370     }
371 
372     mod all {
373         wasmtime::component::bindgen!({
374             inline: "
375                 package foo:foo;
376 
377                 world foo {
378                     import foo: func();
379                 }
380             ",
381             imports: { default: trappable },
382         });
383         struct X;
384 
385         impl FooImports for X {
386             fn foo(&mut self) -> wasmtime::Result<()> {
387                 Ok(())
388             }
389         }
390     }
391 
392     mod some {
393         wasmtime::component::bindgen!({
394             inline: "
395                 package foo:foo;
396 
397                 world foo {
398                     import foo: func();
399                     import bar: func();
400                 }
401             ",
402             imports: { "foo": trappable },
403         });
404         struct X;
405 
406         impl FooImports for X {
407             fn foo(&mut self) -> wasmtime::Result<()> {
408                 Ok(())
409             }
410             fn bar(&mut self) {}
411         }
412     }
413 
414     mod across_interfaces {
415         use wasmtime::component::Resource;
416 
417         wasmtime::component::bindgen!({
418             inline: "
419                 package foo:foo;
420 
421                 interface a {
422                     foo: func();
423                     bar: func();
424 
425                     resource r {
426                         constructor();
427                         foo: func();
428                         bar: static func();
429                     }
430                 }
431 
432                 world foo {
433                     import a;
434                     import foo: func();
435                     import bar: func();
436                     import i: interface {
437                         foo: func();
438                         bar: func();
439                     }
440 
441                 }
442             ",
443             imports: {
444                 "foo": trappable | exact,
445                 "i/foo": trappable,
446                 "foo:foo/a/foo": trappable,
447             },
448             with: { "foo:foo/a/r": R },
449         });
450 
451         struct X;
452         pub struct R;
453 
454         impl FooImports for X {
455             fn foo(&mut self) -> wasmtime::Result<()> {
456                 Ok(())
457             }
458             fn bar(&mut self) {}
459         }
460 
461         impl i::Host for X {
462             fn foo(&mut self) -> wasmtime::Result<()> {
463                 Ok(())
464             }
465             fn bar(&mut self) {}
466         }
467 
468         impl foo::foo::a::Host for X {
469             fn foo(&mut self) -> wasmtime::Result<()> {
470                 Ok(())
471             }
472             fn bar(&mut self) {}
473         }
474 
475         impl foo::foo::a::HostR for X {
476             fn new(&mut self) -> Resource<R> {
477                 loop {}
478             }
479             fn foo(&mut self, _: Resource<R>) {}
480             fn bar(&mut self) {}
481             fn drop(&mut self, _: Resource<R>) -> wasmtime::Result<()> {
482                 Ok(())
483             }
484         }
485     }
486 
487     mod resources {
488         use wasmtime::component::Resource;
489 
490         wasmtime::component::bindgen!({
491             inline: "
492                 package foo:foo;
493 
494                 interface a {
495                     resource r {
496                         constructor();
497                         foo: func();
498                         bar: static func();
499                     }
500                 }
501 
502                 world foo {
503                     import a;
504 
505                 }
506             ",
507             imports: {
508                 "foo:foo/a/[constructor]r": trappable,
509                 "foo:foo/a/[method]r.foo": trappable,
510                 "foo:foo/a/[static]r.bar": trappable,
511             },
512             with: { "foo:foo/a/r": R },
513         });
514 
515         struct X;
516         pub struct R;
517 
518         impl foo::foo::a::Host for X {}
519 
520         impl foo::foo::a::HostR for X {
521             fn new(&mut self) -> wasmtime::Result<Resource<R>> {
522                 loop {}
523             }
524             fn foo(&mut self, _: Resource<R>) -> wasmtime::Result<()> {
525                 Ok(())
526             }
527             fn bar(&mut self) -> wasmtime::Result<()> {
528                 Ok(())
529             }
530             fn drop(&mut self, _: Resource<R>) -> wasmtime::Result<()> {
531                 Ok(())
532             }
533         }
534     }
535 }
536 
537 mod custom_derives {
538     use std::collections::{HashSet, hash_map::RandomState};
539 
540     wasmtime::component::bindgen!({
541         inline: "
542             package my:inline;
543 
544             interface blah {
545                 variant abc {
546                     a,
547                     b,
548                     c
549                 }
550 
551                 record foo {
552                     field1: string,
553                     field2: list<u32>,
554                     field3: abc
555                 }
556 
557                 bar: func(cool: foo);
558             }
559 
560             world baz {
561                 import blah;
562             }
563         ",
564         // Clone is included by default almost everywhere, so include it here to make sure it
565         // doesn't conflict
566         additional_derives: [serde::Serialize, serde::Deserialize, Hash, Clone, PartialEq, Eq],
567     });
568 
569     use my::inline::blah::{Abc, Foo, Host};
570 
571     struct X;
572 
573     impl Host for X {
574         fn bar(&mut self, cool: Foo) {
575             // Check that built in derives that I've added actually work by seeing that this hashes
576             let _blah: HashSet<Foo, RandomState> = HashSet::from_iter([Foo {
577                 field1: "hello".to_string(),
578                 field2: vec![1, 2, 3],
579                 field3: Abc::B,
580             }]);
581 
582             // Check that the attributes from an external crate actually work. If they don't work,
583             // compilation will fail here
584             let _ = serde_json::to_string(&cool);
585         }
586     }
587 }
588 
589 mod with_and_mixing_async {
590     mod with_async {
591         wasmtime::component::bindgen!({
592             inline: "
593                 package my:inline;
594                 interface foo {
595                     type t = u32;
596                     foo: func() -> t;
597                 }
598                 interface bar {
599                     use foo.{t};
600                     bar: func() -> t;
601                 }
602                 world x {
603                     import bar;
604                 }
605             ",
606             imports: {
607                 "my:inline/bar/bar": async,
608             },
609         });
610     }
611 
612     mod without_async {
613         wasmtime::component::bindgen!({
614             inline: "
615                 package my:inline;
616                 interface foo {
617                     type t = u32;
618                     foo: func() -> t;
619                 }
620                 interface bar {
621                     use foo.{t};
622                     bar: func() -> t;
623                 }
624                 world x {
625                     import bar;
626                 }
627             ",
628             with: {
629                 "my:inline/foo": super::with_async::my::inline::foo,
630             },
631             require_store_data_send: true,
632         });
633     }
634 
635     mod third {
636         wasmtime::component::bindgen!({
637             inline: "
638                 package my:inline;
639                 interface foo {
640                     type t = u32;
641                     foo: func() -> t;
642                 }
643                 interface bar {
644                     use foo.{t};
645                     bar: func() -> t;
646                 }
647                 interface baz {
648                     use bar.{t};
649                     baz: func() -> t;
650                 }
651                 world x {
652                     import baz;
653                 }
654             ",
655             with: {
656                 "my:inline/foo": super::with_async::my::inline::foo,
657                 "my:inline/bar": super::without_async::my::inline::bar,
658             },
659             require_store_data_send: true,
660         });
661     }
662 }
663 
664 mod trappable_error_type_and_versions {
665     struct MyError;
666 
667     mod package_no_version_path_no_version {
668         wasmtime::component::bindgen!({
669             inline: "
670                 package my:inline;
671                 interface i {
672                     enum e { a, b, c }
673                 }
674                 world foo {}
675             ",
676             trappable_error_type: {
677                 "my:inline/i/e" => super::MyError,
678             },
679         });
680     }
681     mod package_version_path_no_version {
682         wasmtime::component::bindgen!({
683             inline: "
684                 package my:[email protected];
685                 interface i {
686                     enum e { a, b, c }
687                 }
688                 world foo {}
689             ",
690             trappable_error_type: {
691                 "my:inline/i/e" => super::MyError,
692             },
693         });
694     }
695     mod package_version_path_version {
696         wasmtime::component::bindgen!({
697             inline: "
698                 package my:[email protected];
699                 interface i {
700                     enum e { a, b, c }
701                 }
702                 world foo {}
703             ",
704             trappable_error_type: {
705                 "my:inline/[email protected]/e" => super::MyError,
706             },
707         });
708     }
709 }
710 
711 mod paths {
712     mod multiple_paths {
713         wasmtime::component::bindgen!({
714             world: "test:paths/test",
715             inline: r#"
716             package test:paths;
717             world test {
718                 import paths:path1/test;
719                 export paths:path2/test;
720             }
721             "#,
722             path: ["tests/codegen/path1", "tests/codegen/path2"],
723         });
724     }
725 }
726