1 include!(concat!(env!("OUT_DIR"), "/gen.rs"));
2 
3 use std::borrow::Cow;
4 use std::collections::HashMap;
5 use std::io::IsTerminal;
6 use std::sync::{Arc, Mutex};
7 use wasmtime::{CacheStore, Config, Engine};
8 
9 /// The wasi-tests binaries use these environment variables to determine their
10 /// expected behavior.
11 /// Used by all of the tests/ which execute the wasi-tests binaries.
wasi_tests_environment() -> &'static [(&'static str, &'static str)]12 pub fn wasi_tests_environment() -> &'static [(&'static str, &'static str)] {
13     #[cfg(windows)]
14     {
15         &[
16             ("ERRNO_MODE_WINDOWS", "1"),
17             // Windows does not support dangling links or symlinks in the filesystem.
18             ("NO_DANGLING_FILESYSTEM", "1"),
19             // Windows does not support renaming a directory to an empty directory -
20             // empty directory must be deleted.
21             ("NO_RENAME_DIR_TO_EMPTY_DIR", "1"),
22             ("RENAME_DIR_ONTO_FILE", "1"),
23         ]
24     }
25     #[cfg(all(unix, not(target_os = "macos")))]
26     {
27         &[("ERRNO_MODE_UNIX", "1")]
28     }
29     #[cfg(target_os = "macos")]
30     {
31         &[("ERRNO_MODE_MACOS", "1")]
32     }
33 }
34 
stdio_is_terminal() -> bool35 pub fn stdio_is_terminal() -> bool {
36     std::io::stdin().is_terminal()
37         && std::io::stdout().is_terminal()
38         && std::io::stderr().is_terminal()
39 }
40 
41 // Simple incremental cache used during tests to help improve test runtime.
42 //
43 // Many tests take a similar module (e.g. a component, a preview1 thing, sync,
44 // async, etc) and run it in different contexts and this improve cache hit rates
45 // across usages by sharing one incremental cache across tests.
cache_store() -> Arc<dyn CacheStore>46 fn cache_store() -> Arc<dyn CacheStore> {
47     #[derive(Debug)]
48     struct MyCache;
49 
50     static CACHE: Mutex<Option<HashMap<Vec<u8>, Vec<u8>>>> = Mutex::new(None);
51 
52     impl CacheStore for MyCache {
53         fn get(&self, key: &[u8]) -> Option<Cow<'_, [u8]>> {
54             let mut cache = CACHE.lock().unwrap();
55             let cache = cache.get_or_insert_with(HashMap::new);
56             cache.get(key).map(|s| s.to_vec().into())
57         }
58 
59         fn insert(&self, key: &[u8], value: Vec<u8>) -> bool {
60             let mut cache = CACHE.lock().unwrap();
61             let cache = cache.get_or_insert_with(HashMap::new);
62             cache.insert(key.to_vec(), value);
63             true
64         }
65     }
66 
67     Arc::new(MyCache)
68 }
69 
70 /// Helper to create an `Engine` with a pre-configured `Config` that uses a
71 /// cache for faster building of modules.
engine(configure: impl FnOnce(&mut Config)) -> Engine72 pub fn engine(configure: impl FnOnce(&mut Config)) -> Engine {
73     let mut config = Config::new();
74     config.wasm_component_model(true);
75     config
76         .enable_incremental_compilation(cache_store())
77         .unwrap();
78     configure(&mut config);
79     Engine::new(&config).unwrap()
80 }
81