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