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