xref: /wasmtime-44.0.1/tests/all/module.rs (revision d3087487)
1 use anyhow::Result;
2 use wasmtime::*;
3 
4 #[test]
5 fn checks_incompatible_target() -> Result<()> {
6     let mut target = target_lexicon::Triple::host();
7     target.operating_system = target_lexicon::OperatingSystem::Unknown;
8     match Module::new(
9         &Engine::new(Config::new().target(&target.to_string())?)?,
10         "(module)",
11     ) {
12         Ok(_) => unreachable!(),
13         Err(e) => assert!(
14             format!("{:?}", e).contains("configuration does not match the host"),
15             "bad error: {:?}",
16             e
17         ),
18     }
19 
20     Ok(())
21 }
22 
23 #[test]
24 fn caches_across_engines() {
25     let c = Config::new();
26 
27     let bytes = Module::new(&Engine::new(&c).unwrap(), "(module)")
28         .unwrap()
29         .serialize()
30         .unwrap();
31 
32     unsafe {
33         let res = Module::deserialize(&Engine::default(), &bytes);
34         assert!(res.is_ok());
35 
36         // differ in runtime settings
37         let res = Module::deserialize(
38             &Engine::new(Config::new().static_memory_maximum_size(0)).unwrap(),
39             &bytes,
40         );
41         assert!(res.is_err());
42 
43         // differ in wasm features enabled (which can affect
44         // runtime/compilation settings)
45         let res = Module::deserialize(
46             &Engine::new(Config::new().wasm_simd(false)).unwrap(),
47             &bytes,
48         );
49         assert!(res.is_err());
50     }
51 }
52 
53 #[test]
54 fn aot_compiles() -> Result<()> {
55     let engine = Engine::default();
56     let bytes = engine.precompile_module(
57         "(module (func (export \"f\") (param i32) (result i32) local.get 0))".as_bytes(),
58     )?;
59 
60     let module = unsafe { Module::deserialize(&engine, &bytes)? };
61 
62     let mut store = Store::new(&engine, ());
63     let instance = Instance::new(&mut store, &module, &[])?;
64 
65     let f = instance.get_typed_func::<i32, i32, _>(&mut store, "f")?;
66     assert_eq!(f.call(&mut store, 101)?, 101);
67 
68     Ok(())
69 }
70 
71 #[test]
72 fn serialize_deterministic() {
73     let engine = Engine::default();
74 
75     let assert_deterministic = |wasm: &str| {
76         let p1 = engine.precompile_module(wasm.as_bytes()).unwrap();
77         let p2 = engine.precompile_module(wasm.as_bytes()).unwrap();
78         if p1 != p2 {
79             panic!("precompile_module not determinisitc for:\n{}", wasm);
80         }
81 
82         let module1 = Module::new(&engine, wasm).unwrap();
83         let a1 = module1.serialize().unwrap();
84         let a2 = module1.serialize().unwrap();
85         if a1 != a2 {
86             panic!("Module::serialize not determinisitc for:\n{}", wasm);
87         }
88 
89         let module2 = Module::new(&engine, wasm).unwrap();
90         let b1 = module2.serialize().unwrap();
91         let b2 = module2.serialize().unwrap();
92         if b1 != b2 {
93             panic!("Module::serialize not determinisitc for:\n{}", wasm);
94         }
95 
96         if a1 != b2 {
97             panic!("not matching across modules:\n{}", wasm);
98         }
99         if b1 != p2 {
100             panic!("not matching across engine/module:\n{}", wasm);
101         }
102     };
103 
104     assert_deterministic("(module)");
105     assert_deterministic("(module (func))");
106     assert_deterministic("(module (func nop))");
107     assert_deterministic("(module (func) (func (param i32)))");
108     assert_deterministic("(module (func (export \"f\")) (func (export \"y\")))");
109     assert_deterministic("(module (func $f) (func $g))");
110     assert_deterministic("(module (data \"\") (data \"\"))");
111     assert_deterministic("(module (elem) (elem))");
112 }
113 
114 // This test asserts that the optimization to transform separate data segments
115 // into an initialization image doesn't unnecessarily create a massive module by
116 // accident with a very large initialization image in it.
117 #[test]
118 fn serialize_not_overly_massive() -> Result<()> {
119     let mut config = Config::new();
120     config.memory_guaranteed_dense_image_size(1 << 20);
121     let engine = Engine::new(&config)?;
122 
123     let assert_smaller_than_1mb = |module: &str| -> Result<()> {
124         println!("{}", module);
125         let bytes = Module::new(&engine, module)?.serialize()?;
126         assert!(bytes.len() < (1 << 20));
127         Ok(())
128     };
129 
130     // Tons of space between data segments should use sparse initialization,
131     // along with various permutations of empty and nonempty segments.
132     assert_smaller_than_1mb(
133         r#"(module
134             (memory 20000)
135             (data (i32.const 0) "a")
136             (data (i32.const 0x200000) "b")
137         )"#,
138     )?;
139     assert_smaller_than_1mb(
140         r#"(module
141             (memory 20000)
142             (data (i32.const 0) "a")
143             (data (i32.const 0x200000) "")
144         )"#,
145     )?;
146     assert_smaller_than_1mb(
147         r#"(module
148             (memory 20000)
149             (data (i32.const 0) "")
150             (data (i32.const 0x200000) "b")
151         )"#,
152     )?;
153     assert_smaller_than_1mb(
154         r#"(module
155             (memory 20000)
156             (data (i32.const 0) "")
157             (data (i32.const 0x200000) "")
158         )"#,
159     )?;
160 
161     // lone data segment
162     assert_smaller_than_1mb(
163         r#"(module
164             (memory 20000)
165             (data (i32.const 0x200000) "b")
166         )"#,
167     )?;
168 
169     Ok(())
170 }
171