Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/component_model/dynamic.rs
1691 views
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
927