Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/module_serialize.rs
1692 views
1
use anyhow::bail;
2
use std::fs::{self, OpenOptions};
3
use wasmtime::*;
4
5
fn serialize(engine: &Engine, wat: &str) -> Result<Vec<u8>> {
6
let module = Module::new(&engine, wat)?;
7
Ok(module.serialize()?)
8
}
9
10
unsafe fn deserialize_and_instantiate(store: &mut Store<()>, buffer: &[u8]) -> Result<Instance> {
11
let module = unsafe { Module::deserialize(store.engine(), buffer)? };
12
Ok(Instance::new(store, &module, &[])?)
13
}
14
15
#[test]
16
fn test_version_mismatch() -> Result<()> {
17
let engine = Engine::default();
18
let buffer = serialize(&engine, "(module)")?;
19
20
let mut config = Config::new();
21
config
22
.module_version(ModuleVersionStrategy::Custom("custom!".to_owned()))
23
.unwrap();
24
let custom_version_engine = Engine::new(&config).unwrap();
25
match unsafe { Module::deserialize(&custom_version_engine, &buffer) } {
26
Ok(_) => bail!("expected deserialization to fail"),
27
Err(e) => assert!(
28
e.to_string()
29
.starts_with("Module was compiled with incompatible version")
30
),
31
}
32
33
let mut config = Config::new();
34
config.module_version(ModuleVersionStrategy::None).unwrap();
35
let none_version_engine = Engine::new(&config).unwrap();
36
unsafe { Module::deserialize(&none_version_engine, &buffer) }
37
.expect("accepts the wasmtime versioned module");
38
39
let buffer = serialize(&custom_version_engine, "(module)")?;
40
unsafe { Module::deserialize(&none_version_engine, &buffer) }
41
.expect("accepts the custom versioned module");
42
43
Ok(())
44
}
45
46
#[test]
47
#[cfg_attr(miri, ignore)]
48
fn test_module_serialize_simple() -> Result<()> {
49
let buffer = serialize(
50
&Engine::default(),
51
"(module (func (export \"run\") (result i32) i32.const 42))",
52
)?;
53
54
let mut store = Store::default();
55
let instance = unsafe { deserialize_and_instantiate(&mut store, &buffer)? };
56
let run = instance.get_typed_func::<(), i32>(&mut store, "run")?;
57
let result = run.call(&mut store, ())?;
58
59
assert_eq!(42, result);
60
Ok(())
61
}
62
63
#[test]
64
#[cfg_attr(miri, ignore)]
65
fn test_module_serialize_fail() -> Result<()> {
66
let buffer = serialize(
67
&Engine::default(),
68
"(module (func (export \"run\") (result i32) i32.const 42))",
69
)?;
70
71
let mut config = Config::new();
72
config.memory_reservation(0);
73
let mut store = Store::new(&Engine::new(&config)?, ());
74
match unsafe { deserialize_and_instantiate(&mut store, &buffer) } {
75
Ok(_) => bail!("expected failure at deserialization"),
76
Err(_) => (),
77
}
78
Ok(())
79
}
80
81
#[test]
82
#[cfg_attr(miri, ignore)]
83
fn test_deserialize_from_file() -> Result<()> {
84
serialize_and_call("(module (func (export \"run\") (result i32) i32.const 42))")?;
85
serialize_and_call(
86
"(module
87
(func (export \"run\") (result i32)
88
call $answer)
89
90
(func $answer (result i32)
91
i32.const 42))
92
",
93
)?;
94
return Ok(());
95
96
fn serialize_and_call(wat: &str) -> Result<()> {
97
let mut store = Store::<()>::default();
98
let td = tempfile::TempDir::new()?;
99
let buffer = serialize(store.engine(), wat)?;
100
101
let path = td.path().join("module.bin");
102
fs::write(&path, &buffer)?;
103
let module = unsafe { Module::deserialize_file(store.engine(), &path)? };
104
let instance = Instance::new(&mut store, &module, &[])?;
105
let func = instance.get_typed_func::<(), i32>(&mut store, "run")?;
106
assert_eq!(func.call(&mut store, ())?, 42);
107
108
// Try an already opened file as well.
109
let mut open_options = OpenOptions::new();
110
open_options.read(true);
111
#[cfg(target_os = "windows")]
112
{
113
use std::os::windows::prelude::*;
114
use windows_sys::Win32::Storage::FileSystem::*;
115
open_options.access_mode(FILE_GENERIC_READ | FILE_GENERIC_EXECUTE);
116
}
117
118
let file = open_options.open(&path)?;
119
let module = unsafe { Module::deserialize_open_file(store.engine(), file)? };
120
let instance = Instance::new(&mut store, &module, &[])?;
121
let func = instance.get_typed_func::<(), i32>(&mut store, "run")?;
122
assert_eq!(func.call(&mut store, ())?, 42);
123
124
Ok(())
125
}
126
}
127
128
#[test]
129
#[cfg_attr(miri, ignore)]
130
fn deserialize_from_serialized() -> Result<()> {
131
let engine = Engine::default();
132
let buffer1 = serialize(
133
&engine,
134
"(module (func (export \"run\") (result i32) i32.const 42))",
135
)?;
136
let buffer2 = unsafe { Module::deserialize(&engine, &buffer1)?.serialize()? };
137
assert!(buffer1 == buffer2);
138
Ok(())
139
}
140
141
#[test]
142
#[cfg_attr(miri, ignore)]
143
fn detect_precompiled() -> Result<()> {
144
let engine = Engine::default();
145
let buffer = serialize(
146
&engine,
147
"(module (func (export \"run\") (result i32) i32.const 42))",
148
)?;
149
assert_eq!(Engine::detect_precompiled(&[]), None);
150
assert_eq!(Engine::detect_precompiled(&buffer[..5]), None);
151
assert_eq!(
152
Engine::detect_precompiled(&buffer),
153
Some(Precompiled::Module)
154
);
155
Ok(())
156
}
157
158