1 #![cfg(not(miri))]
2 
3 use super::{Param, Type, make_echo_component, make_echo_component_with_params};
4 use anyhow::Result;
5 use wasmtime::component::types::{self, Case, ComponentItem, Field};
6 use wasmtime::component::{Component, Linker, ResourceType, Val};
7 use wasmtime::{Module, Store};
8 use wasmtime_component_util::REALLOC_AND_FREE;
9 use wasmtime_test_util::component::FuncExt;
10 
11 #[test]
12 fn primitives() -> Result<()> {
13     let engine = super::engine();
14     let mut store = Store::new(&engine, ());
15     let mut output = [Val::Bool(false)];
16 
17     for (input, ty, param) in [
18         (Val::Bool(true), "bool", Param(Type::U8, Some(0))),
19         (Val::S8(-42), "s8", Param(Type::S8, Some(0))),
20         (Val::U8(42), "u8", Param(Type::U8, Some(0))),
21         (Val::S16(-4242), "s16", Param(Type::S16, Some(0))),
22         (Val::U16(4242), "u16", Param(Type::U16, Some(0))),
23         (Val::S32(-314159265), "s32", Param(Type::I32, Some(0))),
24         (Val::U32(314159265), "u32", Param(Type::I32, Some(0))),
25         (Val::S64(-31415926535897), "s64", Param(Type::I64, Some(0))),
26         (Val::U64(31415926535897), "u64", Param(Type::I64, Some(0))),
27         (
28             Val::Float32(3.14159265),
29             "float32",
30             Param(Type::F32, Some(0)),
31         ),
32         (
33             Val::Float64(3.14159265),
34             "float64",
35             Param(Type::F64, Some(0)),
36         ),
37         (Val::Char('��'), "char", Param(Type::I32, Some(0))),
38     ] {
39         let component = Component::new(&engine, make_echo_component_with_params(ty, &[param]))?;
40         let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
41         let func = instance.get_func(&mut store, "echo").unwrap();
42         func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
43 
44         assert_eq!(input, output[0]);
45     }
46 
47     // Sad path: type mismatch
48 
49     let component = Component::new(
50         &engine,
51         make_echo_component_with_params("float64", &[Param(Type::F64, Some(0))]),
52     )?;
53     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
54     let func = instance.get_func(&mut store, "echo").unwrap();
55     let err = func
56         .call_and_post_return(&mut store, &[Val::U64(42)], &mut output)
57         .unwrap_err();
58 
59     assert!(err.to_string().contains("type mismatch"), "{err}");
60 
61     // Sad path: arity mismatch (too many)
62 
63     let err = func
64         .call_and_post_return(
65             &mut store,
66             &[Val::Float64(3.14159265), Val::Float64(3.14159265)],
67             &mut output,
68         )
69         .unwrap_err();
70 
71     assert!(
72         err.to_string().contains("expected 1 argument(s), got 2"),
73         "{err}"
74     );
75 
76     // Sad path: arity mismatch (too few)
77 
78     let err = func
79         .call_and_post_return(&mut store, &[], &mut output)
80         .unwrap_err();
81     assert!(
82         err.to_string().contains("expected 1 argument(s), got 0"),
83         "{err}"
84     );
85 
86     let err = func
87         .call_and_post_return(&mut store, &output, &mut [])
88         .unwrap_err();
89     assert!(
90         err.to_string().contains("expected 1 result(s), got 0"),
91         "{err}"
92     );
93 
94     Ok(())
95 }
96 
97 #[test]
98 fn strings() -> Result<()> {
99     let engine = super::engine();
100     let mut store = Store::new(&engine, ());
101 
102     let component = Component::new(&engine, make_echo_component("string", 8))?;
103     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
104     let func = instance.get_func(&mut store, "echo").unwrap();
105     let input = Val::String("hello, component!".into());
106     let mut output = [Val::Bool(false)];
107     func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
108     assert_eq!(input, output[0]);
109 
110     Ok(())
111 }
112 
113 #[test]
114 fn lists() -> Result<()> {
115     let engine = super::engine();
116     let mut store = Store::new(&engine, ());
117 
118     let component = Component::new(&engine, make_echo_component("(list u32)", 8))?;
119     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
120     let func = instance.get_func(&mut store, "echo").unwrap();
121     let input = Val::List(vec![
122         Val::U32(32343),
123         Val::U32(79023439),
124         Val::U32(2084037802),
125     ]);
126     let mut output = [Val::Bool(false)];
127     func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
128 
129     assert_eq!(input, output[0]);
130 
131     // Sad path: type mismatch
132 
133     let err = Val::List(vec![
134         Val::U32(32343),
135         Val::U32(79023439),
136         Val::Float32(3.14159265),
137     ]);
138     let err = func
139         .call_and_post_return(&mut store, &[err], &mut output)
140         .unwrap_err();
141     assert!(err.to_string().contains("type mismatch"), "{err}");
142 
143     Ok(())
144 }
145 
146 #[test]
147 fn records() -> Result<()> {
148     let engine = super::engine();
149     let mut store = Store::new(&engine, ());
150 
151     let component = Component::new(
152         &engine,
153         make_echo_component_with_params(
154             r#"
155                 (type $c' (record
156                     (field "D" bool)
157                     (field "E" u32)
158                 ))
159                 (export $c "c" (type $c'))
160                 (type $Foo' (record
161                     (field "A" u32)
162                     (field "B" float64)
163                     (field "C" $c)
164                 ))
165             "#,
166             &[
167                 Param(Type::I32, Some(0)),
168                 Param(Type::F64, Some(8)),
169                 Param(Type::U8, Some(16)),
170                 Param(Type::I32, Some(20)),
171             ],
172         ),
173     )?;
174     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
175     let func = instance.get_func(&mut store, "echo").unwrap();
176     let input = Val::Record(vec![
177         ("A".into(), Val::U32(32343)),
178         ("B".into(), Val::Float64(3.14159265)),
179         (
180             "C".into(),
181             Val::Record(vec![
182                 ("D".into(), Val::Bool(false)),
183                 ("E".into(), Val::U32(2084037802)),
184             ]),
185         ),
186     ]);
187     let mut output = [Val::Bool(false)];
188     func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
189 
190     assert_eq!(input, output[0]);
191 
192     // Sad path: type mismatch
193 
194     let err = Val::Record(vec![
195         ("A".into(), Val::S32(32343)),
196         ("B".into(), Val::Float64(3.14159265)),
197         (
198             "C".into(),
199             Val::Record(vec![
200                 ("D".into(), Val::Bool(false)),
201                 ("E".into(), Val::U32(2084037802)),
202             ]),
203         ),
204     ]);
205     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
206     let func = instance.get_func(&mut store, "echo").unwrap();
207     let err = func
208         .call_and_post_return(&mut store, &[err], &mut output)
209         .unwrap_err();
210     assert!(err.to_string().contains("type mismatch"), "{err}");
211 
212     // Sad path: too many fields
213 
214     let err = Val::Record(vec![
215         ("A".into(), Val::U32(32343)),
216         ("B".into(), Val::Float64(3.14159265)),
217         (
218             "C".into(),
219             Val::Record(vec![
220                 ("D".into(), Val::Bool(false)),
221                 ("E".into(), Val::U32(2084037802)),
222             ]),
223         ),
224         ("F".into(), Val::Bool(true)),
225     ]);
226     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
227     let func = instance.get_func(&mut store, "echo").unwrap();
228     let err = func
229         .call_and_post_return(&mut store, &[err], &mut output)
230         .unwrap_err();
231     assert!(
232         err.to_string().contains("expected 3 fields, got 4"),
233         "{err}"
234     );
235 
236     // Sad path: too few fields
237 
238     let err = Val::Record(vec![
239         ("A".into(), Val::U32(32343)),
240         ("B".into(), Val::Float64(3.14159265)),
241     ]);
242     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
243     let func = instance.get_func(&mut store, "echo").unwrap();
244     let err = func
245         .call_and_post_return(&mut store, &[err], &mut output)
246         .unwrap_err();
247     assert!(
248         err.to_string().contains("expected 3 fields, got 2"),
249         "{err}"
250     );
251 
252     Ok(())
253 }
254 
255 #[test]
256 fn variants() -> Result<()> {
257     let engine = super::engine();
258     let mut store = Store::new(&engine, ());
259 
260     let fragment = r#"
261                 (type $c' (record (field "D" bool) (field "E" u32)))
262                 (export $c "c" (type $c'))
263                 (type $Foo' (variant
264                     (case "A" u32)
265                     (case "B" float64)
266                     (case "C" $c)
267                 ))
268             "#;
269 
270     let component = Component::new(
271         &engine,
272         make_echo_component_with_params(
273             fragment,
274             &[
275                 Param(Type::U8, Some(0)),
276                 Param(Type::I64, Some(8)),
277                 Param(Type::I32, None),
278             ],
279         ),
280     )?;
281     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
282     let func = instance.get_func(&mut store, "echo").unwrap();
283     let input = Val::Variant("B".into(), Some(Box::new(Val::Float64(3.14159265))));
284     let mut output = [Val::Bool(false)];
285     func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
286 
287     assert_eq!(input, output[0]);
288 
289     // Do it again, this time using case "C"
290 
291     let component = Component::new(
292         &engine,
293         make_echo_component_with_params(
294             fragment,
295             &[
296                 Param(Type::U8, Some(0)),
297                 Param(Type::I64, Some(8)),
298                 Param(Type::I32, Some(12)),
299             ],
300         ),
301     )?;
302     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
303     let func = instance.get_func(&mut store, "echo").unwrap();
304     let input = Val::Variant(
305         "C".into(),
306         Some(Box::new(Val::Record(vec![
307             ("D".into(), Val::Bool(true)),
308             ("E".into(), Val::U32(314159265)),
309         ]))),
310     );
311     func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
312 
313     assert_eq!(input, output[0]);
314 
315     // Sad path: type mismatch
316 
317     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
318     let func = instance.get_func(&mut store, "echo").unwrap();
319     let err = Val::Variant("B".into(), Some(Box::new(Val::U64(314159265))));
320     let err = func
321         .call_and_post_return(&mut store, &[err], &mut output)
322         .unwrap_err();
323     assert!(err.to_string().contains("type mismatch"), "{err}");
324 
325     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
326     let func = instance.get_func(&mut store, "echo").unwrap();
327     let err = Val::Variant("B".into(), None);
328     let err = func
329         .call_and_post_return(&mut store, &[err], &mut output)
330         .unwrap_err();
331     assert!(
332         err.to_string().contains("expected a payload for case `B`"),
333         "{err}"
334     );
335 
336     // Sad path: unknown case
337 
338     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
339     let func = instance.get_func(&mut store, "echo").unwrap();
340     let err = Val::Variant("D".into(), Some(Box::new(Val::U64(314159265))));
341     let err = func
342         .call_and_post_return(&mut store, &[err], &mut output)
343         .unwrap_err();
344     assert!(err.to_string().contains("unknown variant case"), "{err}");
345 
346     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
347     let func = instance.get_func(&mut store, "echo").unwrap();
348     let err = Val::Variant("D".into(), None);
349     let err = func
350         .call_and_post_return(&mut store, &[err], &mut output)
351         .unwrap_err();
352     assert!(err.to_string().contains("unknown variant case"), "{err}");
353 
354     // Make sure we lift variants which have cases of different sizes with the correct alignment
355 
356     let component = Component::new(
357         &engine,
358         make_echo_component_with_params(
359             r#"
360                 (type $c' (record (field "D" bool) (field "E" u32)))
361                 (export $c "c" (type $c'))
362                 (type $a' (variant
363                     (case "A" u32)
364                     (case "B" float64)
365                     (case "C" $c)
366                 ))
367                 (export $a "a" (type $a'))
368                 (type $Foo' (record
369                     (field "A" $a)
370                     (field "B" u32)
371                 ))
372             "#,
373             &[
374                 Param(Type::U8, Some(0)),
375                 Param(Type::I64, Some(8)),
376                 Param(Type::I32, None),
377                 Param(Type::I32, Some(16)),
378             ],
379         ),
380     )?;
381     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
382     let func = instance.get_func(&mut store, "echo").unwrap();
383     let input = Val::Record(vec![
384         (
385             "A".into(),
386             Val::Variant("A".into(), Some(Box::new(Val::U32(314159265)))),
387         ),
388         ("B".into(), Val::U32(628318530)),
389     ]);
390     func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
391 
392     assert_eq!(input, output[0]);
393 
394     Ok(())
395 }
396 
397 #[test]
398 fn flags() -> Result<()> {
399     let engine = super::engine();
400     let mut store = Store::new(&engine, ());
401 
402     let component = Component::new(
403         &engine,
404         make_echo_component_with_params(
405             r#"(flags "A" "B" "C" "D" "E")"#,
406             &[Param(Type::U8, Some(0))],
407         ),
408     )?;
409     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
410     let func = instance.get_func(&mut store, "echo").unwrap();
411     let input = Val::Flags(vec!["B".into(), "D".into()]);
412     let mut output = [Val::Bool(false)];
413     func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
414 
415     assert_eq!(input, output[0]);
416 
417     // Sad path: unknown flags
418 
419     let err = Val::Flags(vec!["B".into(), "D".into(), "F".into()]);
420     let err = func
421         .call_and_post_return(&mut store, &[err], &mut output)
422         .unwrap_err();
423     assert!(err.to_string().contains("unknown flag"), "{err}");
424 
425     Ok(())
426 }
427 
428 #[test]
429 fn everything() -> Result<()> {
430     // This serves to test both nested types and storing parameters on the heap (i.e. exceeding `MAX_STACK_PARAMS`)
431 
432     let engine = super::engine();
433     let mut store = Store::new(&engine, ());
434 
435     let component = Component::new(
436         &engine,
437         make_echo_component_with_params(
438             r#"
439                 (type $b' (enum "a" "b"))
440                 (export $b "b" (type $b'))
441                 (type $c' (record (field "D" bool) (field "E" u32)))
442                 (export $c "c" (type $c'))
443                 (type $f' (flags "G" "H" "I"))
444                 (export $f "f" (type $f'))
445                 (type $m' (record (field "N" bool) (field "O" u32)))
446                 (export $m "m" (type $m'))
447                 (type $j' (variant
448                     (case "K" u32)
449                     (case "L" float64)
450                     (case "M" $m)
451                 ))
452                 (export $j "j" (type $j'))
453 
454                 (type $Foo' (record
455                     (field "A" u32)
456                     (field "B" $b)
457                     (field "C" $c)
458                     (field "F" (list $f))
459                     (field "J" $j)
460                     (field "P" s8)
461                     (field "Q" s16)
462                     (field "R" s32)
463                     (field "S" s64)
464                     (field "T" float32)
465                     (field "U" float64)
466                     (field "V" string)
467                     (field "W" char)
468                     (field "Y" (tuple u32 u32))
469                     (field "AA" (option u32))
470                     (field "BB" (result string (error string)))
471                 ))
472             "#,
473             &[
474                 Param(Type::I32, Some(0)),
475                 Param(Type::U8, Some(4)),
476                 Param(Type::U8, Some(5)),
477                 Param(Type::I32, Some(8)),
478                 Param(Type::I32, Some(12)),
479                 Param(Type::I32, Some(16)),
480                 Param(Type::U8, Some(20)),
481                 Param(Type::I64, Some(28)),
482                 Param(Type::I32, Some(32)),
483                 Param(Type::S8, Some(36)),
484                 Param(Type::S16, Some(38)),
485                 Param(Type::I32, Some(40)),
486                 Param(Type::I64, Some(48)),
487                 Param(Type::F32, Some(56)),
488                 Param(Type::F64, Some(64)),
489                 Param(Type::I32, Some(72)),
490                 Param(Type::I32, Some(76)),
491                 Param(Type::I32, Some(80)),
492                 Param(Type::I32, Some(84)),
493                 Param(Type::I32, Some(88)),
494                 Param(Type::I64, Some(96)),
495                 Param(Type::U8, Some(104)),
496                 Param(Type::I32, Some(108)),
497                 Param(Type::U8, Some(112)),
498                 Param(Type::I32, Some(116)),
499                 Param(Type::I32, Some(120)),
500             ],
501         ),
502     )?;
503     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
504     let func = instance.get_func(&mut store, "echo").unwrap();
505     let input = Val::Record(vec![
506         ("A".into(), Val::U32(32343)),
507         ("B".into(), Val::Enum("b".to_string())),
508         (
509             "C".into(),
510             Val::Record(vec![
511                 ("D".to_string(), Val::Bool(false)),
512                 ("E".to_string(), Val::U32(2084037802)),
513             ]),
514         ),
515         (
516             "F".into(),
517             Val::List(vec![Val::Flags(vec!["G".to_string(), "I".to_string()])]),
518         ),
519         (
520             "J".into(),
521             Val::Variant("L".to_string(), Some(Box::new(Val::Float64(3.14159265)))),
522         ),
523         ("P".into(), Val::S8(42)),
524         ("Q".into(), Val::S16(4242)),
525         ("R".into(), Val::S32(42424242)),
526         ("S".into(), Val::S64(424242424242424242)),
527         ("T".into(), Val::Float32(3.14159265)),
528         ("U".into(), Val::Float64(3.14159265)),
529         ("V".into(), Val::String("wow, nice types".to_string())),
530         ("W".into(), Val::Char('��')),
531         ("Y".into(), Val::Tuple(vec![Val::U32(42), Val::U32(24)])),
532         (
533             "AA".into(),
534             Val::Option(Some(Box::new(Val::U32(314159265)))),
535         ),
536         (
537             "BB".into(),
538             Val::Result(Ok(Some(Box::new(Val::String("no problem".to_string()))))),
539         ),
540     ]);
541     let mut output = [Val::Bool(false)];
542     func.call_and_post_return(&mut store, &[input.clone()], &mut output)?;
543 
544     assert_eq!(input, output[0]);
545 
546     Ok(())
547 }
548 
549 #[test]
550 fn introspection() -> Result<()> {
551     let engine = super::engine();
552 
553     let component = Component::new(
554         &engine,
555         format!(
556             r#"
557             (component
558                 (import "res" (type $res (sub resource)))
559 
560                 (import "ai" (instance $i))
561                 (import "bi" (instance $i2 (export "m" (core module))))
562 
563                 (alias export $i2 "m" (core module $m))
564 
565                 (type $t (func (param "a" u32) (result u32)))
566                 (component $a
567                   (core module $m
568                     (func (export "add-five") (param i32) (result i32)
569                       local.get 0
570                       i32.const 5
571                       i32.add)
572                   )
573                   (core instance $m (instantiate $m))
574                   (func (export "add-five") (type $t) (canon lift (core func $m "add-five")))
575                 )
576                 (component $b
577                   (import "interface-v1" (instance $i
578                     (export "add-five" (func (type $t)))))
579                   (core module $m
580                     (func $add-five (import "interface-0.1.0" "add-five") (param i32) (result i32))
581                     (func) ;; causes index out of bounds
582                     (func (export "run") (result i32) i32.const 0 call $add-five)
583                   )
584                   (core func $add-five (canon lower (func $i "add-five")))
585                   (core instance $i (instantiate 0
586                     (with "interface-0.1.0" (instance
587                       (export "add-five" (func $add-five))
588                     ))
589                   ))
590                   (func (result u32) (canon lift (core func $i "run")))
591                   (export "run" (func 1))
592                 )
593                 (instance $a (instantiate $a))
594                 (instance $b (instantiate $b (with "interface-v1" (instance $a))))
595                 (export "run" (func $b "run"))
596 
597                 (component $c
598                     (component $c
599                         (export "m" (core module $m))
600                     )
601                     (instance $c (instantiate $c))
602                     (export "i" (instance $c))
603                 )
604                 (instance $c (instantiate $c))
605                 (export "i" (instance $c))
606                 (export "r" (instance $i))
607                 (export "r2" (instance $i2))
608 
609                 (type $b' (enum "a" "b"))
610                 (export $b "b" (type $b'))
611                 (type $c' (record (field "D" bool) (field "E" u32)))
612                 (export $c "c" (type $c'))
613                 (type $f' (flags "G" "H" "I"))
614                 (export $f "f" (type $f'))
615                 (type $m' (record (field "N" bool) (field "O" u32)))
616                 (export $m "m" (type $m'))
617                 (type $j' (variant
618                     (case "K" u32)
619                     (case "L" float64)
620                     (case "M" $m)
621                 ))
622                 (export $j "j" (type $j'))
623 
624                 (type $Foo' (record
625                     (field "A" u32)
626                     (field "B" $b)
627                     (field "C" $c)
628                     (field "F" (list $f))
629                     (field "J" $j)
630                     (field "P" s8)
631                     (field "Q" s16)
632                     (field "R" s32)
633                     (field "S" s64)
634                     (field "T" float32)
635                     (field "U" float64)
636                     (field "V" string)
637                     (field "W" char)
638                     (field "Y" (tuple u32 u32))
639                     (field "AA" (option u32))
640                     (field "BB" (result string (error string)))
641                     (field "CC" (own $res))
642                 ))
643                 (export $Foo "foo" (type $Foo'))
644 
645                 (core module $m2
646                     (func (export "f") (param i32) (result i32)
647                         local.get 0
648                     )
649                     (memory (export "memory") 1)
650                     {REALLOC_AND_FREE}
651                 )
652                 (core instance $i3 (instantiate $m2))
653 
654                 (func (export "fn") (param "x" (option $Foo)) (result (option (tuple u32 u32)))
655                     (canon lift
656                         (core func $i3 "f")
657                         (memory $i3 "memory")
658                         (realloc (func $i3 "realloc"))
659                     )
660                 )
661             )
662         "#
663         ),
664     )?;
665 
666     struct MyType;
667 
668     let mut linker = Linker::<()>::new(&engine);
669     linker
670         .root()
671         .resource("res", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
672     linker.instance("ai")?;
673     linker
674         .instance("bi")?
675         .module("m", &Module::new(&engine, "(module)")?)?;
676 
677     let component_ty = linker.substituted_component_type(&component)?;
678 
679     let mut imports = component_ty.imports(linker.engine());
680     assert_eq!(imports.len(), 3);
681     let (name, res_ty) = imports.next().unwrap();
682     assert_eq!(name, "res");
683     let ComponentItem::Resource(res_ty) = res_ty else {
684         panic!("`res` import item of wrong type")
685     };
686     assert_eq!(res_ty, ResourceType::host::<MyType>());
687 
688     let (name, ai_ty) = imports.next().unwrap();
689     assert_eq!(name, "ai");
690     let ComponentItem::ComponentInstance(ai_ty) = ai_ty else {
691         panic!("`ai` import item of wrong type")
692     };
693     assert_eq!(ai_ty.exports(linker.engine()).len(), 0);
694 
695     let (name, bi_ty) = imports.next().unwrap();
696     assert_eq!(name, "bi");
697     let ComponentItem::ComponentInstance(bi_ty) = bi_ty else {
698         panic!("`bi` import item of wrong type")
699     };
700     let mut bi_exports = bi_ty.exports(linker.engine());
701     assert_eq!(bi_exports.len(), 1);
702     let (name, bi_m_ty) = bi_exports.next().unwrap();
703     assert_eq!(name, "m");
704     let ComponentItem::Module(bi_m_ty) = bi_m_ty else {
705         panic!("`bi.m` import item of wrong type")
706     };
707     assert_eq!(bi_m_ty.imports(linker.engine()).len(), 0);
708     assert_eq!(bi_m_ty.exports(linker.engine()).len(), 0);
709 
710     let mut exports = component_ty.exports(linker.engine());
711     assert_eq!(exports.len(), 11);
712 
713     let (name, run_ty) = exports.next().unwrap();
714     assert_eq!(name, "run");
715     let ComponentItem::ComponentFunc(run_ty) = run_ty else {
716         panic!("`run` export item of wrong type")
717     };
718     assert_eq!(run_ty.params().len(), 0);
719 
720     let mut run_results = run_ty.results();
721     assert_eq!(run_results.len(), 1);
722     assert_eq!(run_results.next().unwrap(), types::Type::U32);
723 
724     let (name, i_ty) = exports.next().unwrap();
725     assert_eq!(name, "i");
726     let ComponentItem::ComponentInstance(i_ty) = i_ty else {
727         panic!("`i` export item of wrong type")
728     };
729     let mut i_ty_exports = i_ty.exports(linker.engine());
730     assert_eq!(i_ty_exports.len(), 1);
731     let (name, i_i_ty) = i_ty_exports.next().unwrap();
732     assert_eq!(name, "i");
733     let ComponentItem::ComponentInstance(i_i_ty) = i_i_ty else {
734         panic!("`i.i` import item of wrong type")
735     };
736     let mut i_i_ty_exports = i_i_ty.exports(linker.engine());
737     assert_eq!(i_i_ty_exports.len(), 1);
738     let (name, i_i_m_ty) = i_i_ty_exports.next().unwrap();
739     assert_eq!(name, "m");
740     let ComponentItem::Module(i_i_m_ty) = i_i_m_ty else {
741         panic!("`i.i.m` import item of wrong type")
742     };
743     assert_eq!(i_i_m_ty.imports(linker.engine()).len(), 0);
744     assert_eq!(i_i_m_ty.exports(linker.engine()).len(), 0);
745 
746     let (name, r_ty) = exports.next().unwrap();
747     assert_eq!(name, "r");
748     let ComponentItem::ComponentInstance(r_ty) = r_ty else {
749         panic!("`r` export item of wrong type")
750     };
751     assert_eq!(r_ty.exports(linker.engine()).len(), 0);
752 
753     let (name, r2_ty) = exports.next().unwrap();
754     assert_eq!(name, "r2");
755     let ComponentItem::ComponentInstance(r2_ty) = r2_ty else {
756         panic!("`r2` export item of wrong type")
757     };
758     let mut r2_exports = r2_ty.exports(linker.engine());
759     assert_eq!(r2_exports.len(), 1);
760     let (name, r2_m_ty) = r2_exports.next().unwrap();
761     assert_eq!(name, "m");
762     let ComponentItem::Module(r2_m_ty) = r2_m_ty else {
763         panic!("`r2.m` export item of wrong type")
764     };
765     assert_eq!(r2_m_ty.imports(linker.engine()).len(), 0);
766     assert_eq!(r2_m_ty.exports(linker.engine()).len(), 0);
767 
768     let (name, b_ty) = exports.next().unwrap();
769     assert_eq!(name, "b");
770     let ComponentItem::Type(b_ty) = b_ty else {
771         panic!("`b` export item of wrong type")
772     };
773     assert_eq!(b_ty.unwrap_enum().names().collect::<Vec<_>>(), ["a", "b"]);
774 
775     let (name, c_ty) = exports.next().unwrap();
776     assert_eq!(name, "c");
777     let ComponentItem::Type(c_ty) = c_ty else {
778         panic!("`c` export item of wrong type")
779     };
780     let mut fields = c_ty.unwrap_record().fields();
781     {
782         let Field { name, ty } = fields.next().unwrap();
783         assert_eq!(name, "D");
784         assert_eq!(ty, types::Type::Bool);
785         let Field { name, ty } = fields.next().unwrap();
786         assert_eq!(name, "E");
787         assert_eq!(ty, types::Type::U32);
788     }
789 
790     let (name, f_ty) = exports.next().unwrap();
791     assert_eq!(name, "f");
792     let ComponentItem::Type(f_ty) = f_ty else {
793         panic!("`f` export item of wrong type")
794     };
795     assert_eq!(
796         f_ty.unwrap_flags().names().collect::<Vec<_>>(),
797         ["G", "H", "I"]
798     );
799 
800     let (name, m_ty) = exports.next().unwrap();
801     assert_eq!(name, "m");
802     let ComponentItem::Type(m_ty) = m_ty else {
803         panic!("`m` export item of wrong type")
804     };
805     {
806         let mut fields = m_ty.unwrap_record().fields();
807         let Field { name, ty } = fields.next().unwrap();
808         assert_eq!(name, "N");
809         assert_eq!(ty, types::Type::Bool);
810         let Field { name, ty } = fields.next().unwrap();
811         assert_eq!(name, "O");
812         assert_eq!(ty, types::Type::U32);
813     }
814 
815     let (name, j_ty) = exports.next().unwrap();
816     assert_eq!(name, "j");
817     let ComponentItem::Type(j_ty) = j_ty else {
818         panic!("`j` export item of wrong type")
819     };
820     let mut cases = j_ty.unwrap_variant().cases();
821     {
822         let Case { name, ty } = cases.next().unwrap();
823         assert_eq!(name, "K");
824         assert_eq!(ty, Some(types::Type::U32));
825         let Case { name, ty } = cases.next().unwrap();
826         assert_eq!(name, "L");
827         assert_eq!(ty, Some(types::Type::Float64));
828         let Case { name, ty } = cases.next().unwrap();
829         assert_eq!(name, "M");
830         assert_eq!(ty, Some(m_ty));
831     }
832 
833     let (name, foo_ty) = exports.next().unwrap();
834     assert_eq!(name, "foo");
835     let ComponentItem::Type(foo_ty) = foo_ty else {
836         panic!("`foo` export item of wrong type")
837     };
838     {
839         let mut fields = foo_ty.unwrap_record().fields();
840         assert_eq!(fields.len(), 17);
841         let Field { name, ty } = fields.next().unwrap();
842         assert_eq!(name, "A");
843         assert_eq!(ty, types::Type::U32);
844         let Field { name, ty } = fields.next().unwrap();
845         assert_eq!(name, "B");
846         assert_eq!(ty, b_ty);
847         let Field { name, ty } = fields.next().unwrap();
848         assert_eq!(name, "C");
849         assert_eq!(ty, c_ty);
850         let Field { name, ty } = fields.next().unwrap();
851         assert_eq!(name, "F");
852         let ty = ty.unwrap_list();
853         assert_eq!(ty.ty(), f_ty);
854         let Field { name, ty } = fields.next().unwrap();
855         assert_eq!(name, "J");
856         assert_eq!(ty, j_ty);
857         let Field { name, ty } = fields.next().unwrap();
858         assert_eq!(name, "P");
859         assert_eq!(ty, types::Type::S8);
860         let Field { name, ty } = fields.next().unwrap();
861         assert_eq!(name, "Q");
862         assert_eq!(ty, types::Type::S16);
863         let Field { name, ty } = fields.next().unwrap();
864         assert_eq!(name, "R");
865         assert_eq!(ty, types::Type::S32);
866         let Field { name, ty } = fields.next().unwrap();
867         assert_eq!(name, "S");
868         assert_eq!(ty, types::Type::S64);
869         let Field { name, ty } = fields.next().unwrap();
870         assert_eq!(name, "T");
871         assert_eq!(ty, types::Type::Float32);
872         let Field { name, ty } = fields.next().unwrap();
873         assert_eq!(name, "U");
874         assert_eq!(ty, types::Type::Float64);
875         let Field { name, ty } = fields.next().unwrap();
876         assert_eq!(name, "V");
877         assert_eq!(ty, types::Type::String);
878         let Field { name, ty } = fields.next().unwrap();
879         assert_eq!(name, "W");
880         assert_eq!(ty, types::Type::Char);
881         let Field { name, ty } = fields.next().unwrap();
882         assert_eq!(name, "Y");
883         assert_eq!(
884             ty.unwrap_tuple().types().collect::<Vec<_>>(),
885             [types::Type::U32, types::Type::U32]
886         );
887         let Field { name, ty } = fields.next().unwrap();
888         assert_eq!(name, "AA");
889         assert_eq!(ty.unwrap_option().ty(), types::Type::U32);
890         let Field { name, ty } = fields.next().unwrap();
891         assert_eq!(name, "BB");
892         let ty = ty.unwrap_result();
893         assert_eq!(ty.ok(), Some(types::Type::String));
894         assert_eq!(ty.err(), Some(types::Type::String));
895         let Field { name, ty } = fields.next().unwrap();
896         assert_eq!(name, "CC");
897         assert_eq!(*ty.unwrap_own(), res_ty);
898     }
899 
900     let (name, fn_ty) = exports.next().unwrap();
901     assert_eq!(name, "fn");
902     let ComponentItem::ComponentFunc(fn_ty) = fn_ty else {
903         panic!("`fn` export item of wrong type")
904     };
905     let mut params = fn_ty.params();
906     assert_eq!(params.len(), 1);
907     let (name, param) = params.next().unwrap();
908     assert_eq!(name, "x");
909     assert_eq!(param.unwrap_option().ty(), foo_ty);
910 
911     let mut results = fn_ty.results();
912     assert_eq!(results.len(), 1);
913     assert_eq!(
914         results
915             .next()
916             .unwrap()
917             .unwrap_option()
918             .ty()
919             .unwrap_tuple()
920             .types()
921             .collect::<Vec<_>>(),
922         [types::Type::U32, types::Type::U32]
923     );
924     Ok(())
925 }
926