Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wizer/tests/all/component.rs
2459 views
1
use anyhow::{Context, Result, bail};
2
use wasmtime::component::{Component, Instance, Linker, Val};
3
use wasmtime::{Config, Engine, Store};
4
use wasmtime_wizer::Wizer;
5
6
fn fail_wizening(msg: &str, wasm: &[u8]) -> Result<()> {
7
let _ = env_logger::try_init();
8
9
let wasm = wat::parse_bytes(wasm)?;
10
log::debug!(
11
"testing wizening failure for wasm:\n{}",
12
wasmprinter::print_bytes(&wasm)?
13
);
14
match Wizer::new().instrument_component(&wasm) {
15
Ok(_) => bail!("expected wizening to fail"),
16
Err(e) => {
17
let err = format!("{e}");
18
if !err.contains(msg) {
19
bail!("unexpected error: {err}");
20
}
21
Ok(())
22
}
23
}
24
}
25
26
#[test]
27
fn unsupported_constructs() -> Result<()> {
28
fail_wizening(
29
"does not currently support component imports",
30
br#"(component
31
(import "x" (component))
32
)"#,
33
)?;
34
35
fail_wizening(
36
"nested components with modules not currently supported",
37
br#"(component
38
(component (core module))
39
)"#,
40
)?;
41
fail_wizening(
42
"nested components with modules not currently supported",
43
br#"(component
44
(component)
45
(component (core module))
46
)"#,
47
)?;
48
fail_wizening(
49
"wizer does not currently support module imports",
50
br#"(component
51
(component (import "x" (core module)))
52
)"#,
53
)?;
54
fail_wizening(
55
"wizer does not currently support module aliases",
56
br#"(component
57
(core module $a)
58
(component
59
(core instance (instantiate $a))
60
)
61
)"#,
62
)?;
63
fail_wizening(
64
"wizer does not currently support component aliases",
65
br#"(component
66
(component $a)
67
(component
68
(instance (instantiate $a))
69
)
70
)"#,
71
)?;
72
73
fail_wizening(
74
"does not currently support component aliases",
75
br#"(component
76
(import "x" (instance $i (export "x" (component))))
77
(alias export $i "x" (component $c))
78
)"#,
79
)?;
80
81
fail_wizening(
82
"does not currently support module imports",
83
br#"(component
84
(import "x" (core module))
85
)"#,
86
)?;
87
88
fail_wizening(
89
"does not currently support module exports",
90
br#"(component
91
(core module $x)
92
(export "x" (core module $x))
93
)"#,
94
)?;
95
96
fail_wizening(
97
"does not currently support module aliases",
98
br#"(component
99
(import "x" (instance $i (export "x" (core module))))
100
(alias export $i "x" (core module $c))
101
)"#,
102
)?;
103
fail_wizening(
104
"does not currently support component start functions",
105
br#"(component
106
(import "f" (func $f))
107
(start $f)
108
)"#,
109
)?;
110
111
fail_wizening(
112
"modules may be instantiated at most once",
113
br#"(component
114
(core module $a)
115
(core instance $a1 (instantiate $a))
116
(core instance $a2 (instantiate $a))
117
)"#,
118
)?;
119
120
Ok(())
121
}
122
123
fn store() -> Result<Store<()>> {
124
let mut config = Config::new();
125
config.async_support(true);
126
let engine = Engine::new(&config)?;
127
Ok(Store::new(&engine, ()))
128
}
129
130
async fn instantiate(store: &mut Store<()>, component: &Component) -> Result<Instance> {
131
let mut linker = Linker::new(store.engine());
132
linker.define_unknown_imports_as_traps(component)?;
133
linker.instantiate_async(store, component).await
134
}
135
136
async fn wizen(wat: &str) -> Result<Vec<u8>> {
137
let _ = env_logger::try_init();
138
let wasm = wat::parse_str(wat)?;
139
140
log::debug!(
141
"=== PreWizened Wasm ==========================================================\n\
142
{}\n\
143
===========================================================================",
144
wasmprinter::print_bytes(&wasm).unwrap()
145
);
146
let mut store = store()?;
147
let wasm = Wizer::new()
148
.run_component(&mut store, &wasm, instantiate)
149
.await?;
150
log::debug!(
151
"=== Wizened Wasm ==========================================================\n\
152
{}\n\
153
===========================================================================",
154
wasmprinter::print_bytes(&wasm).unwrap()
155
);
156
if log::log_enabled!(log::Level::Debug) {
157
std::fs::write("test.wasm", &wasm).unwrap();
158
}
159
160
Ok(wasm)
161
}
162
163
async fn wizen_and_run_wasm(expected: u32, wat: &str) -> Result<()> {
164
let wasm = wizen(wat).await?;
165
166
let mut store = store()?;
167
let module =
168
Component::new(store.engine(), wasm).context("Wasm test case failed to compile")?;
169
170
let linker = Linker::new(store.engine());
171
let instance = linker.instantiate_async(&mut store, &module).await?;
172
173
let run = instance.get_func(&mut store, "run").ok_or_else(|| {
174
anyhow::anyhow!("the test Wasm component does not export a `run` function")
175
})?;
176
177
let mut actual = [Val::U8(0)];
178
run.call_async(&mut store, &[], &mut actual).await?;
179
let actual = match actual[0] {
180
Val::U32(x) => x,
181
_ => anyhow::bail!("expected an u32 result"),
182
};
183
anyhow::ensure!(
184
expected == actual,
185
"expected `{expected}`, found `{actual}`",
186
);
187
188
Ok(())
189
}
190
191
#[tokio::test]
192
async fn simple() -> Result<()> {
193
wizen_and_run_wasm(
194
42,
195
r#"(component
196
(core module $m
197
(func (export "init"))
198
199
(func (export "run") (result i32)
200
i32.const 42
201
)
202
)
203
(core instance $i (instantiate $m))
204
(func (export "run") (result u32) (canon lift (core func $i "run")))
205
(func (export "wizer-initialize") (canon lift (core func $i "init")))
206
)"#,
207
)
208
.await?;
209
210
Ok(())
211
}
212
213
#[tokio::test]
214
async fn snapshot_global_i32() -> Result<()> {
215
wizen_and_run_wasm(
216
1,
217
r#"(component
218
(core module $m
219
(global $g (mut i32) i32.const 0)
220
(func (export "init") (global.set $g (i32.const 1)))
221
(func (export "run") (result i32) global.get $g)
222
)
223
(core instance $i (instantiate $m))
224
(func (export "run") (result u32) (canon lift (core func $i "run")))
225
(func (export "wizer-initialize") (canon lift (core func $i "init")))
226
)"#,
227
)
228
.await?;
229
230
Ok(())
231
}
232
233
#[tokio::test]
234
async fn snapshot_global_i64() -> Result<()> {
235
wizen_and_run_wasm(
236
1,
237
r#"(component
238
(core module $m
239
(global $g (mut i64) i64.const 0)
240
(func (export "init") (global.set $g (i64.const 1)))
241
(func (export "run") (result i32)
242
global.get $g
243
i32.wrap_i64
244
)
245
)
246
(core instance $i (instantiate $m))
247
(func (export "run") (result u32) (canon lift (core func $i "run")))
248
(func (export "wizer-initialize") (canon lift (core func $i "init")))
249
)"#,
250
)
251
.await?;
252
253
Ok(())
254
}
255
256
#[tokio::test]
257
async fn snapshot_global_f32() -> Result<()> {
258
wizen_and_run_wasm(
259
1,
260
r#"(component
261
(core module $m
262
(global $g (mut f32) f32.const 0)
263
(func (export "init") (global.set $g (f32.const 1)))
264
(func (export "run") (result i32)
265
global.get $g
266
i32.trunc_f32_s)
267
)
268
(core instance $i (instantiate $m))
269
(func (export "run") (result u32) (canon lift (core func $i "run")))
270
(func (export "wizer-initialize") (canon lift (core func $i "init")))
271
)"#,
272
)
273
.await?;
274
275
Ok(())
276
}
277
278
#[tokio::test]
279
async fn snapshot_global_f64() -> Result<()> {
280
wizen_and_run_wasm(
281
1,
282
r#"(component
283
(core module $m
284
(global $g (mut f64) f64.const 0)
285
(func (export "init") (global.set $g (f64.const 1)))
286
(func (export "run") (result i32)
287
global.get $g
288
i32.trunc_f64_s)
289
)
290
(core instance $i (instantiate $m))
291
(func (export "run") (result u32) (canon lift (core func $i "run")))
292
(func (export "wizer-initialize") (canon lift (core func $i "init")))
293
)"#,
294
)
295
.await?;
296
297
Ok(())
298
}
299
300
#[test]
301
fn v128_globals() -> Result<()> {
302
fail_wizening(
303
"component wizening does not support v128 globals",
304
br#"(component
305
(core module $a
306
(global (export "x") (mut v128) (v128.const i32x4 1 2 3 4))
307
)
308
(core instance (instantiate $a))
309
)"#,
310
)
311
}
312
313
#[tokio::test]
314
async fn snapshot_memory() -> Result<()> {
315
wizen_and_run_wasm(
316
201,
317
r#"(component
318
(core module $m
319
(memory 1)
320
(func (export "init")
321
i32.const 200
322
i32.const 100
323
i32.store
324
i32.const 300
325
i32.const 101
326
i32.store
327
)
328
(func (export "run") (result i32)
329
i32.const 200
330
i32.load
331
i32.const 300
332
i32.load
333
i32.add
334
)
335
)
336
(core instance $i (instantiate $m))
337
(func (export "run") (result u32) (canon lift (core func $i "run")))
338
(func (export "wizer-initialize") (canon lift (core func $i "init")))
339
)"#,
340
)
341
.await?;
342
343
Ok(())
344
}
345
346
#[tokio::test]
347
async fn nested_components() -> Result<()> {
348
wizen_and_run_wasm(
349
42,
350
r#"(component
351
(component $a)
352
(instance (instantiate $a))
353
(instance (export "hi") (instantiate $a))
354
355
(component $b
356
(type $t string)
357
(import "x" (type (eq $t)))
358
(component $a)
359
(instance (instantiate $a))
360
(instance (export "hi") (instantiate $a))
361
)
362
(type $x string)
363
(instance (instantiate $b
364
(with "x" (type $x))
365
))
366
(instance (export "hi2") (instantiate $b
367
(with "x" (type $x))
368
))
369
370
(core module $m
371
(func (export "init"))
372
(func (export "run") (result i32) i32.const 42)
373
)
374
(core instance $i (instantiate $m))
375
(func (export "run") (result u32) (canon lift (core func $i "run")))
376
(func (export "wizer-initialize") (canon lift (core func $i "init")))
377
)"#,
378
)
379
.await?;
380
381
Ok(())
382
}
383
384
#[tokio::test]
385
async fn multiple_modules() -> Result<()> {
386
wizen_and_run_wasm(
387
100 + 101 + 200 + 201 + 7 + 112,
388
r#"(component
389
(core module $a
390
(memory 1)
391
(global $g (export "g") (mut i32) (i32.const 0))
392
393
(func (export "init")
394
i32.const 200
395
i32.const 100
396
i32.store
397
i32.const 300
398
i32.const 101
399
i32.store
400
)
401
402
(func (export "run") (result i32)
403
i32.const 200
404
i32.load
405
i32.const 300
406
i32.load
407
i32.add
408
global.get $g
409
i32.add
410
)
411
)
412
(core instance $a (instantiate $a))
413
414
(core module $b
415
(import "a" "g" (global $g (mut i32)))
416
(import "a" "init" (func $init))
417
(import "a" "run" (func $run (result i32)))
418
(memory (export "mem") 1)
419
(func (export "init")
420
call $init
421
i32.const 400
422
i32.const 200
423
i32.store
424
i32.const 500
425
i32.const 201
426
i32.store
427
428
i32.const 111
429
global.set $g
430
)
431
(func (export "run") (result i32)
432
i32.const 400
433
i32.load
434
i32.const 500
435
i32.load
436
i32.add
437
call $run
438
i32.add
439
)
440
)
441
(core instance $b (instantiate $b (with "a" (instance $a))))
442
443
(core module $c
444
(import "a" "g" (global $g (mut i32)))
445
(import "b" "init" (func $init))
446
(import "b" "run" (func $run (result i32)))
447
(import "b" "mem" (memory 1))
448
449
(func (export "init")
450
call $init
451
452
i32.const 1
453
memory.grow
454
i32.const -1
455
i32.eq
456
if unreachable end
457
458
i32.const 65536
459
i32.const 7
460
i32.store
461
462
;; overwrite a#init with a different value, make sure this
463
;; one is snapshot
464
i32.const 112
465
global.set $g
466
)
467
(func (export "run") (result i32)
468
i32.const 65536
469
i32.load
470
call $run
471
i32.add
472
)
473
)
474
(core instance $c (instantiate $c
475
(with "a" (instance $a))
476
(with "b" (instance $b))
477
))
478
479
(func (export "run") (result u32) (canon lift (core func $c "run")))
480
(func (export "wizer-initialize") (canon lift (core func $c "init")))
481
)"#,
482
)
483
.await?;
484
485
Ok(())
486
}
487
488
#[tokio::test]
489
async fn export_is_removed() -> Result<()> {
490
let wasm = wizen(
491
r#"(component
492
(core module $a
493
(func (export "init"))
494
)
495
(core instance $a (instantiate $a))
496
(func $a (canon lift (core func $a "init")))
497
(export "wizer-initialize" (func $a))
498
)"#,
499
)
500
.await?;
501
502
let names = exports(&wasm);
503
assert!(names.is_empty());
504
505
let wasm = wizen(
506
r#"(component
507
(core module $a
508
(func (export "init"))
509
)
510
(core instance $a (instantiate $a))
511
(func $a (canon lift (core func $a "init")))
512
(export "other" (func $a))
513
(export "wizer-initialize" (func $a))
514
)"#,
515
)
516
.await?;
517
let names = exports(&wasm);
518
assert_eq!(names, ["other"]);
519
520
let wasm = wizen(
521
r#"(component
522
(core module $a
523
(func (export "init"))
524
)
525
(core instance $a (instantiate $a))
526
(func $a (canon lift (core func $a "init")))
527
(export "other1" (func $a))
528
(export "wizer-initialize" (func $a))
529
(export "other2" (func $a))
530
)"#,
531
)
532
.await?;
533
let names = exports(&wasm);
534
assert_eq!(names, ["other1", "other2"]);
535
536
let wasm = wizen(
537
r#"(component
538
(core module $a
539
(func (export "init"))
540
)
541
(core instance $a (instantiate $a))
542
(func $a (canon lift (core func $a "init")))
543
(export "other1" (func $a))
544
(export "other2" (func $a))
545
(export "wizer-initialize" (func $a))
546
)"#,
547
)
548
.await?;
549
let names = exports(&wasm);
550
assert_eq!(names, ["other1", "other2"]);
551
552
let wasm = wizen(
553
r#"(component
554
(core module $a
555
(func (export "init"))
556
)
557
(core instance $a (instantiate $a))
558
(func $a (canon lift (core func $a "init")))
559
(export "wizer-initialize" (func $a))
560
(export "other1" (func $a))
561
(export "other2" (func $a))
562
)"#,
563
)
564
.await?;
565
let names = exports(&wasm);
566
assert_eq!(names, ["other1", "other2"]);
567
568
let wasm = wizen(
569
r#"(component
570
(core module $a
571
(func (export "init"))
572
)
573
(core instance $a (instantiate $a))
574
(func $a (canon lift (core func $a "init")))
575
(export $x "other1" (func $a))
576
(export "wizer-initialize" (func $a))
577
(export "other2" (func $x))
578
)"#,
579
)
580
.await?;
581
let names = exports(&wasm);
582
assert_eq!(names, ["other1", "other2"]);
583
584
let wasm = wizen(
585
r#"(component
586
(import "x" (func))
587
(core module $a
588
(func (export "init"))
589
)
590
(core instance $a (instantiate $a))
591
(func $a (canon lift (core func $a "init")))
592
(export $x "other1" (func $a))
593
(export "wizer-initialize" (func $a))
594
(export "other2" (func $x))
595
)"#,
596
)
597
.await?;
598
let names = exports(&wasm);
599
assert_eq!(names, ["other1", "other2"]);
600
601
return Ok(());
602
603
fn exports(wasm: &[u8]) -> Vec<&str> {
604
wasmparser::Parser::new(0)
605
.parse_all(&wasm)
606
.filter_map(|r| r.ok())
607
.filter_map(|payload| match payload {
608
wasmparser::Payload::ComponentExportSection(s) => Some(s),
609
_ => None,
610
})
611
.flat_map(|section| section.into_iter().map(|e| e.unwrap().name.0))
612
.collect()
613
}
614
}
615
616