1 use anyhow::Result;
2 use wasmtime::component::*;
3 use wasmtime::{Module, Store};
4 
5 #[test]
6 #[cfg_attr(miri, ignore)]
7 fn instance_exports() -> Result<()> {
8     let engine = super::engine();
9     let component = r#"
10         (component
11             (import "a" (instance $i))
12             (import "b" (instance $i2 (export "m" (core module))))
13 
14             (alias export $i2 "m" (core module $m))
15 
16             (component $c
17                 (component $c
18                     (export "m" (core module $m))
19                 )
20                 (instance $c (instantiate $c))
21                 (export "i" (instance $c))
22             )
23             (instance $c (instantiate $c))
24             (export "i" (instance $c))
25             (export "r" (instance $i))
26             (export "r2" (instance $i2))
27         )
28     "#;
29     let component = Component::new(&engine, component)?;
30     let mut store = Store::new(&engine, ());
31     let mut linker = Linker::new(&engine);
32     linker.instance("a")?;
33     linker
34         .instance("b")?
35         .module("m", &Module::new(&engine, "(module)")?)?;
36     let instance = linker.instantiate(&mut store, &component)?;
37 
38     assert!(instance
39         .get_export(&mut store, None, "not an instance")
40         .is_none());
41     let i = instance.get_export_index(&mut store, None, "r").unwrap();
42     assert!(instance.get_export(&mut store, Some(&i), "x").is_none());
43     instance.get_export(&mut store, None, "i").unwrap();
44     let i2 = instance.get_export_index(&mut store, None, "r2").unwrap();
45     let m = instance
46         .get_export_index(&mut store, Some(&i2), "m")
47         .unwrap();
48     assert!(instance.get_func(&mut store, &m).is_none());
49     assert!(instance.get_module(&mut store, &m).is_some());
50 
51     let i = instance.get_export_index(&mut store, None, "i").unwrap();
52     let i = instance
53         .get_export_index(&mut store, Some(&i), "i")
54         .unwrap();
55     let m = instance
56         .get_export_index(&mut store, Some(&i), "m")
57         .unwrap();
58     instance.get_module(&mut store, &m).unwrap();
59 
60     Ok(())
61 }
62 
63 #[test]
64 fn export_old_get_new() -> Result<()> {
65     let engine = super::engine();
66     let component = r#"
67         (component
68             (core module $m)
69             (export "a:b/[email protected]" (core module $m))
70 
71             (instance $i (export "m" (core module $m)))
72             (export "a:b/[email protected]" (instance $i))
73         )
74     "#;
75 
76     let component = Component::new(&engine, component)?;
77     component.get_export(None, "a:b/[email protected]").unwrap();
78     let i = component.get_export_index(None, "a:b/[email protected]").unwrap();
79     component.get_export(Some(&i), "m").unwrap();
80 
81     let mut store = Store::new(&engine, ());
82     let linker = Linker::new(&engine);
83     let instance = linker.instantiate(&mut store, &component)?;
84 
85     instance.get_module(&mut store, "a:b/[email protected]").unwrap();
86     instance
87         .get_export(&mut store, None, "a:b/[email protected]")
88         .unwrap();
89 
90     let i = instance
91         .get_export_index(&mut store, None, "a:b/[email protected]")
92         .unwrap();
93     instance.get_export(&mut store, Some(&i), "m").unwrap();
94 
95     Ok(())
96 }
97 
98 #[test]
99 fn export_new_get_old() -> Result<()> {
100     let engine = super::engine();
101     let component = r#"
102         (component
103             (core module $m)
104             (export "a:b/[email protected]" (core module $m))
105 
106             (instance $i (export "m" (core module $m)))
107             (export "a:b/[email protected]" (instance $i))
108         )
109     "#;
110 
111     let component = Component::new(&engine, component)?;
112     component.get_export(None, "a:b/[email protected]").unwrap();
113     let i = component.get_export_index(None, "a:b/[email protected]").unwrap();
114     component.get_export(Some(&i), "m").unwrap();
115 
116     let mut store = Store::new(&engine, ());
117     let linker = Linker::new(&engine);
118     let instance = linker.instantiate(&mut store, &component)?;
119 
120     instance.get_module(&mut store, "a:b/[email protected]").unwrap();
121     instance
122         .get_export(&mut store, None, "a:b/[email protected]")
123         .unwrap();
124 
125     let i = instance
126         .get_export_index(&mut store, None, "a:b/[email protected]")
127         .unwrap();
128     instance.get_export(&mut store, Some(&i), "m").unwrap();
129 
130     Ok(())
131 }
132 
133 #[test]
134 #[cfg_attr(miri, ignore)]
135 fn export_missing_get_max() -> Result<()> {
136     let engine = super::engine();
137     let component = r#"
138         (component
139             (core module $m1)
140             (core module $m2 (import "" "" (func)))
141             (export "a:b/[email protected]" (core module $m1))
142             (export "a:b/[email protected]" (core module $m2))
143         )
144     "#;
145 
146     fn assert_m2(module: &Module) {
147         assert_eq!(module.imports().len(), 1);
148     }
149     fn assert_m1(module: &Module) {
150         assert_eq!(module.imports().len(), 0);
151     }
152 
153     let component = Component::new(&engine, component)?;
154     let mut store = Store::new(&engine, ());
155     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
156 
157     let tests = [
158         ("a:b/[email protected]", assert_m2 as fn(&_)), // no exact, should pick max available
159         ("a:b/[email protected]", assert_m1),           // exact hit
160         ("a:b/[email protected]", assert_m2),           // no exact, should pick max available
161         ("a:b/[email protected]", assert_m2),           // exact hit
162         ("a:b/[email protected]", assert_m2),           // no exact, should pick max available
163     ];
164 
165     for (name, test_fn) in tests {
166         println!("test {name}");
167         let m = component.get_export_index(None, name).unwrap();
168         let m = instance.get_module(&mut store, &m).unwrap();
169         test_fn(&m);
170 
171         let m = instance.get_module(&mut store, name).unwrap();
172         test_fn(&m);
173 
174         let m = instance.get_export_index(&mut store, None, name).unwrap();
175         let m = instance.get_module(&mut store, &m).unwrap();
176         test_fn(&m);
177     }
178 
179     Ok(())
180 }
181