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(&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(&mut store, None, "r2").unwrap();
45     let m = instance.get_export(&mut store, Some(&i2), "m").unwrap();
46     assert!(instance.get_func(&mut store, &m).is_none());
47     assert!(instance.get_module(&mut store, &m).is_some());
48 
49     let i = instance.get_export(&mut store, None, "i").unwrap();
50     let i = instance.get_export(&mut store, Some(&i), "i").unwrap();
51     let m = instance.get_export(&mut store, Some(&i), "m").unwrap();
52     instance.get_module(&mut store, &m).unwrap();
53 
54     Ok(())
55 }
56 
57 #[test]
58 fn export_old_get_new() -> Result<()> {
59     let engine = super::engine();
60     let component = r#"
61         (component
62             (core module $m)
63             (export "a:b/[email protected]" (core module $m))
64 
65             (instance $i (export "m" (core module $m)))
66             (export "a:b/[email protected]" (instance $i))
67         )
68     "#;
69 
70     let component = Component::new(&engine, component)?;
71     component.export_index(None, "a:b/[email protected]").unwrap();
72     let (_, i) = component.export_index(None, "a:b/[email protected]").unwrap();
73     component.export_index(Some(&i), "m").unwrap();
74 
75     let mut store = Store::new(&engine, ());
76     let linker = Linker::new(&engine);
77     let instance = linker.instantiate(&mut store, &component)?;
78 
79     instance.get_module(&mut store, "a:b/[email protected]").unwrap();
80     instance
81         .get_export(&mut store, None, "a:b/[email protected]")
82         .unwrap();
83 
84     let i = instance
85         .get_export(&mut store, None, "a:b/[email protected]")
86         .unwrap();
87     instance.get_export(&mut store, Some(&i), "m").unwrap();
88 
89     Ok(())
90 }
91 
92 #[test]
93 fn export_new_get_old() -> Result<()> {
94     let engine = super::engine();
95     let component = r#"
96         (component
97             (core module $m)
98             (export "a:b/[email protected]" (core module $m))
99 
100             (instance $i (export "m" (core module $m)))
101             (export "a:b/[email protected]" (instance $i))
102         )
103     "#;
104 
105     let component = Component::new(&engine, component)?;
106     component.export_index(None, "a:b/[email protected]").unwrap();
107     let (_, i) = component.export_index(None, "a:b/[email protected]").unwrap();
108     component.export_index(Some(&i), "m").unwrap();
109 
110     let mut store = Store::new(&engine, ());
111     let linker = Linker::new(&engine);
112     let instance = linker.instantiate(&mut store, &component)?;
113 
114     instance.get_module(&mut store, "a:b/[email protected]").unwrap();
115     instance
116         .get_export(&mut store, None, "a:b/[email protected]")
117         .unwrap();
118 
119     let i = instance
120         .get_export(&mut store, None, "a:b/[email protected]")
121         .unwrap();
122     instance.get_export(&mut store, Some(&i), "m").unwrap();
123 
124     Ok(())
125 }
126 
127 #[test]
128 #[cfg_attr(miri, ignore)]
129 fn export_missing_get_max() -> Result<()> {
130     let engine = super::engine();
131     let component = r#"
132         (component
133             (core module $m1)
134             (core module $m2 (import "" "" (func)))
135             (export "a:b/[email protected]" (core module $m1))
136             (export "a:b/[email protected]" (core module $m2))
137         )
138     "#;
139 
140     fn assert_m2(module: &Module) {
141         assert_eq!(module.imports().len(), 1);
142     }
143     fn assert_m1(module: &Module) {
144         assert_eq!(module.imports().len(), 0);
145     }
146 
147     let component = Component::new(&engine, component)?;
148     let mut store = Store::new(&engine, ());
149     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
150 
151     let tests = [
152         ("a:b/[email protected]", assert_m2 as fn(&_)), // no exact, should pick max available
153         ("a:b/[email protected]", assert_m1),           // exact hit
154         ("a:b/[email protected]", assert_m2),           // no exact, should pick max available
155         ("a:b/[email protected]", assert_m2),           // exact hit
156         ("a:b/[email protected]", assert_m2),           // no exact, should pick max available
157     ];
158 
159     for (name, test_fn) in tests {
160         println!("test {name}");
161         let (_, m) = component.export_index(None, name).unwrap();
162         let m = instance.get_module(&mut store, &m).unwrap();
163         test_fn(&m);
164 
165         let m = instance.get_module(&mut store, name).unwrap();
166         test_fn(&m);
167 
168         let m = instance.get_export(&mut store, None, name).unwrap();
169         let m = instance.get_module(&mut store, &m).unwrap();
170         test_fn(&m);
171     }
172 
173     Ok(())
174 }
175