use std::time::Instant;
use bao_engine::value::JsValue;
fn eval_str(rt: &mut bun_runtime::BaoRuntime, code: &str) -> String {
match rt.eval(code, "<keepalive-verify>") {
Ok(JsValue::String(s)) => s,
Ok(JsValue::Number(n)) => format!("{}", n),
Ok(JsValue::Bool(b)) => if b { "true" } else { "false" }.to_string(),
Ok(v) => format!("{:?}", v),
Err(e) => format!("ERROR: {:?}", e),
}
}
#[test]
fn module_server_and_timer_keep_process_alive() {
let mut rt = bun_runtime::BaoRuntime::new().expect("BaoRuntime");
let start = Instant::now();
rt.eval_module(
r#"
const srv = Bun.serve({ port: 0, fetch() { return new Response("ok"); } });
globalThis.__srvPort = srv.port;
setTimeout(function () {
srv.stop();
globalThis.__marker = 'served';
}, 2500);
"#,
"<keepalive-server.mjs>",
)
.expect("module eval must succeed");
assert!(start.elapsed() >= std::time::Duration::from_millis(2400),
"module eval must wait for pending timers (elapsed {:?})", start.elapsed());
assert_eq!(
eval_str(&mut rt, "String(globalThis.__marker)"),
"served",
"server + timer must keep the module loop alive until the timer fires \
(pre-fix: 1000-tick cap expired in ~1.2s and killed the process early)"
);
}
#[test]
fn module_cleared_interval_releases_loop() {
let mut rt = bun_runtime::BaoRuntime::new().expect("BaoRuntime");
let start = Instant::now();
rt.eval_module(
r#"
let ticks = 0;
const iv = setInterval(function () { ticks++; }, 25);
setTimeout(function () {
clearInterval(iv);
globalThis.__marker = 'cleared:ticks=' + (ticks > 0);
}, 400);
"#,
"<keepalive-clear.mjs>",
)
.expect("module eval must succeed");
assert_eq!(
eval_str(&mut rt, "String(globalThis.__marker)"),
"cleared:ticks=true",
"interval must fire at least once before being cleared"
);
assert!(start.elapsed() < std::time::Duration::from_secs(5),
"cleared interval + no handles must release the loop promptly (elapsed {:?})",
start.elapsed());
}
#[test]
fn module_process_exit_unaffected() {
let mut rt = bun_runtime::BaoRuntime::new().expect("BaoRuntime");
rt.eval_module(
r#"
const iv = setInterval(function () {}, 25);
setTimeout(function () {
globalThis.__marker = 'exit-called';
process.exit(0);
}, 200);
"#,
"<keepalive-exit.mjs>",
)
.expect("module eval must succeed");
assert_eq!(
eval_str(&mut rt, "String(globalThis.__marker)"),
"exit-called",
"process.exit must terminate the loop with the pending interval still live"
);
}