#[cfg(any(test, debug_assertions))]
use std::sync::Mutex;
#[cfg(any(test, debug_assertions))]
static TEST_BOOTSTRAP_HOOK: Mutex<Option<fn()>> = Mutex::new(None);
pub fn is_memory_bootstrap_ready() -> Result<bool, ic_memory::RuntimeStateError> {
ic_memory::is_default_memory_manager_bootstrapped()
}
pub fn assert_memory_bootstrap_ready(key: &str) {
match is_memory_bootstrap_ready() {
Ok(true) => return,
Ok(false) => {}
Err(error) => {
panic!("stable memory slot '{key}' could not inspect memory bootstrap: {error}");
}
}
#[cfg(any(test, debug_assertions))]
{
run_test_bootstrap_hook();
match is_memory_bootstrap_ready() {
Ok(true) => return,
Ok(false) => {}
Err(error) => {
panic!(
"stable memory slot '{key}' could not inspect memory bootstrap after the test hook: {error}"
);
}
}
}
panic!(
"stable memory slot '{key}' accessed before memory bootstrap; run Canic memory bootstrap with its host pool first"
);
}
#[cfg(any(test, debug_assertions))]
pub fn install_test_bootstrap_hook(hook: fn()) {
*TEST_BOOTSTRAP_HOOK
.lock()
.expect("test bootstrap hook poisoned") = Some(hook);
}
#[cfg(any(test, debug_assertions))]
#[must_use]
pub fn has_test_bootstrap_hook() -> bool {
TEST_BOOTSTRAP_HOOK
.lock()
.expect("test bootstrap hook poisoned")
.is_some()
}
#[cfg(any(test, debug_assertions))]
fn run_test_bootstrap_hook() {
let hook = *TEST_BOOTSTRAP_HOOK
.lock()
.expect("test bootstrap hook poisoned");
if let Some(hook) = hook {
hook();
}
}