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