Skip to content

Commit 98aea80

Browse files
committed
Add smoketests for WasmCoreDump
1 parent 71529c7 commit 98aea80

3 files changed

Lines changed: 164 additions & 1 deletion

File tree

crates/wasmtime/src/coredump.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::fmt;
22

3-
use crate::{store::StoreOpaque, Global, Instance, Memory, Module, WasmBacktrace};
3+
use crate::{store::StoreOpaque, FrameInfo, Global, Instance, Memory, WasmBacktrace};
44

55
/// Representation of a core dump of a WebAssembly module
66
///
@@ -54,6 +54,31 @@ impl WasmCoreDump {
5454
backtrace,
5555
}
5656
}
57+
58+
/// The stack frames for the CoreDump
59+
pub fn frames(&self) -> &[FrameInfo] {
60+
self.backtrace.frames()
61+
}
62+
63+
/// The names of the modules involved in the CoreDump
64+
pub fn modules(&self) -> &[String] {
65+
self.modules.as_ref()
66+
}
67+
68+
/// The instances involved in the CoreDump
69+
pub fn instances(&self) -> &[Instance] {
70+
self.instances.as_ref()
71+
}
72+
73+
/// The globals involved in the CoreDump
74+
pub fn globals(&self) -> &[Global] {
75+
self.globals.as_ref()
76+
}
77+
78+
/// The memories involve din the CoreDump
79+
pub fn memories(&self) -> &[Memory] {
80+
self.memories.as_ref()
81+
}
5782
}
5883

5984
impl fmt::Display for WasmCoreDump {

tests/all/coredump.rs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
use anyhow::{bail, Result};
2+
use wasmtime::*;
3+
4+
#[test]
5+
fn test_coredump_attached_to_error() -> Result<()> {
6+
let mut config = Config::default();
7+
config.coredump_on_trap(true);
8+
let engine = Engine::new(&config).unwrap();
9+
let mut store = Store::<()>::new(&engine, ());
10+
11+
let wat = r#"
12+
(module
13+
(func $hello (import "" "hello"))
14+
(func (export "run") (call $hello))
15+
)
16+
"#;
17+
18+
let module = Module::new(store.engine(), wat)?;
19+
let hello_type = FuncType::new(None, None);
20+
let hello_func = Func::new(&mut store, hello_type, |_, _, _| bail!("test 123"));
21+
22+
let instance = Instance::new(&mut store, &module, &[hello_func.into()])?;
23+
let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
24+
25+
let e = run_func.call(&mut store, ()).unwrap_err();
26+
assert!(format!("{e:?}").contains("test 123"));
27+
28+
assert!(
29+
e.downcast_ref::<WasmCoreDump>().is_some(),
30+
"error should contain a WasmCoreDump"
31+
);
32+
33+
Ok(())
34+
}
35+
36+
#[test]
37+
fn test_coredump_has_stack() -> Result<()> {
38+
let mut config = Config::default();
39+
config.coredump_on_trap(true);
40+
let engine = Engine::new(&config).unwrap();
41+
let mut store = Store::<()>::new(&engine, ());
42+
43+
let wat = r#"
44+
(module
45+
(func (export "a")
46+
call $b
47+
)
48+
(func $b
49+
call $c
50+
)
51+
(func $c
52+
unreachable
53+
)
54+
)
55+
"#;
56+
57+
let module = Module::new(store.engine(), wat)?;
58+
let instance = Instance::new(&mut store, &module, &[])?;
59+
let a_func = instance.get_typed_func::<(), ()>(&mut store, "a")?;
60+
61+
let e = a_func.call(&mut store, ()).unwrap_err();
62+
let cd = e.downcast_ref::<WasmCoreDump>().unwrap();
63+
assert_eq!(cd.frames().len(), 3);
64+
assert_eq!(cd.frames()[0].func_name().unwrap(), "c");
65+
assert_eq!(cd.frames()[1].func_name().unwrap(), "b");
66+
assert_eq!(cd.frames()[2].func_name().unwrap(), "a");
67+
Ok(())
68+
}
69+
70+
#[test]
71+
fn test_coredump_has_modules_and_instances() -> Result<()> {
72+
let mut config = Config::default();
73+
config.coredump_on_trap(true);
74+
let engine = Engine::new(&config).unwrap();
75+
let mut linker = Linker::new(&engine);
76+
let mut store = Store::<()>::new(&engine, ());
77+
78+
let wat1 = r#"
79+
(module $foo
80+
(import "bar" "b" (func $b))
81+
(func (export "a")
82+
call $b
83+
)
84+
)
85+
"#;
86+
let wat2 = r#"
87+
(module $bar
88+
(func (export "b")
89+
unreachable
90+
)
91+
)
92+
"#;
93+
let module1 = Module::new(store.engine(), wat1)?;
94+
let module2 = Module::new(store.engine(), wat2)?;
95+
let linking2 = linker.instantiate(&mut store, &module2)?;
96+
linker.instance(&mut store, "bar", linking2)?;
97+
98+
let linking1 = linker.instantiate(&mut store, &module1)?;
99+
let a_func = linking1.get_typed_func::<(), ()>(&mut store, "a")?;
100+
101+
let e = a_func.call(&mut store, ()).unwrap_err();
102+
let cd = e.downcast_ref::<WasmCoreDump>().unwrap();
103+
dbg!(cd);
104+
assert_eq!(cd.modules().len(), 2);
105+
assert_eq!(cd.modules()[0], "foo");
106+
assert_eq!(cd.modules()[1], "bar");
107+
assert_eq!(cd.instances().len(), 2);
108+
Ok(())
109+
}
110+
111+
#[test]
112+
fn test_coredump_has_globals_and_memory() -> Result<()> {
113+
let mut config = Config::default();
114+
config.coredump_on_trap(true);
115+
let engine = Engine::new(&config).unwrap();
116+
let mut store = Store::<()>::new(&engine, ());
117+
118+
let wat = r#"
119+
(module
120+
(memory (export "memory") 2)
121+
(global (export "myglobal") i32 (i32.const 65536))
122+
(func (export "a") (result i32)
123+
unreachable
124+
)
125+
)
126+
"#;
127+
128+
let module = Module::new(store.engine(), wat)?;
129+
let instance = Instance::new(&mut store, &module, &[])?;
130+
let a_func = instance.get_typed_func::<(), i32>(&mut store, "a")?;
131+
let e = a_func.call(&mut store, ()).unwrap_err();
132+
let cd = e.downcast_ref::<WasmCoreDump>().unwrap();
133+
assert_eq!(cd.globals().len(), 1);
134+
assert_eq!(cd.memories().len(), 1);
135+
136+
Ok(())
137+
}

tests/all/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod async_functions;
44
mod call_hook;
55
mod cli_tests;
66
mod component_model;
7+
mod coredump;
78
mod custom_signal_handler;
89
mod debug;
910
mod epoch_interruption;

0 commit comments

Comments
 (0)