use bao_engine::context::JsContext;
use bao_engine::value::JsValue;
use std::sync::OnceLock;
static TEST_SERIAL_LOCK: OnceLock<std::sync::Mutex<()>> = OnceLock::new();
fn test_serial_lock() -> &'static std::sync::Mutex<()> {
TEST_SERIAL_LOCK.get_or_init(|| std::sync::Mutex::new(()))
}
fn serial_guard() -> std::sync::MutexGuard<'static, ()> {
test_serial_lock().lock().unwrap_or_else(|e| e.into_inner())
}
fn eval_string(ctx: &mut JsContext, source: &str) -> String {
match ctx.eval(source, "<test>") {
Ok(JsValue::String(s)) => s,
Ok(JsValue::Number(n)) => format!("{}", n),
Ok(JsValue::Bool(b)) => if b { "true" } else { "false" }.to_string(),
_ => String::new(),
}
}
#[test]
fn test_secure_context_set_key_stores_pem() {
let _guard = serial_guard();
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
let result = eval_string(
&mut ctx,
r#"
var tls = require('tls');
var sc = tls.createSecureContext();
sc.setKey("-----BEGIN PRIVATE KEY-----\nfakekey\n-----END PRIVATE KEY-----");
// setKey should not throw and should store the PEM
"ok"
"#,
);
assert_eq!(result, "ok");
bun_runtime::shutdown_thread_sm();
}
#[test]
fn test_secure_context_set_cert_stores_pem() {
let _guard = serial_guard();
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
let result = eval_string(
&mut ctx,
r#"
var tls = require('tls');
var sc = tls.createSecureContext();
sc.setCert("-----BEGIN CERTIFICATE-----\nfakecert\n-----END CERTIFICATE-----");
"ok"
"#,
);
assert_eq!(result, "ok");
bun_runtime::shutdown_thread_sm();
}
#[test]
fn test_secure_context_add_ca_cert_appends() {
let _guard = serial_guard();
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
let result = eval_string(
&mut ctx,
r#"
var tls = require('tls');
var sc = tls.createSecureContext();
sc.addCACert("-----BEGIN CERTIFICATE-----\nca1\n-----END CERTIFICATE-----");
sc.addCACert("-----BEGIN CERTIFICATE-----\nca2\n-----END CERTIFICATE-----");
"ok"
"#,
);
assert_eq!(result, "ok");
bun_runtime::shutdown_thread_sm();
}
#[test]
fn test_secure_context_set_ca_replaces() {
let _guard = serial_guard();
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
let result = eval_string(
&mut ctx,
r#"
var tls = require('tls');
var sc = tls.createSecureContext();
sc.setCA("-----BEGIN CERTIFICATE-----\nca\n-----END CERTIFICATE-----");
"ok"
"#,
);
assert_eq!(result, "ok");
bun_runtime::shutdown_thread_sm();
}
#[test]
fn test_create_server_has_event_methods() {
let _guard = serial_guard();
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
let results = eval_string(
&mut ctx,
r#"
var tls = require('tls');
var s = tls.createServer();
var results = [];
results.push(typeof s.on === 'function' ? 'on_ok' : 'on_fail');
results.push(typeof s.once === 'function' ? 'once_ok' : 'once_fail');
results.push(typeof s.emit === 'function' ? 'emit_ok' : 'emit_fail');
results.push(typeof s.removeListener === 'function' ? 'rm_ok' : 'rm_fail');
results.push(typeof s.removeAllListeners === 'function' ? 'rma_ok' : 'rma_fail');
results.join('|')
"#,
);
assert!(results.contains("on_ok"), "createServer should have .on");
assert!(
results.contains("once_ok"),
"createServer should have .once"
);
assert!(
results.contains("emit_ok"),
"createServer should have .emit"
);
assert!(
results.contains("rm_ok"),
"createServer should have .removeListener"
);
assert!(
results.contains("rma_ok"),
"createServer should have .removeAllListeners"
);
bun_runtime::shutdown_thread_sm();
}
#[test]
fn test_create_server_on_registers_callback() {
let _guard = serial_guard();
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
let result = eval_string(
&mut ctx,
r#"
var tls = require('tls');
var s = tls.createServer();
var called = false;
s.on('connection', function() { called = true; });
s.emit('connection');
called ? "emitted" : "not_emitted"
"#,
);
assert_eq!(
result, "emitted",
"createServer .on should register event listener"
);
bun_runtime::shutdown_thread_sm();
}
#[test]
fn test_create_server_with_options_stores_key_cert() {
let _guard = serial_guard();
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
let result = eval_string(
&mut ctx,
r#"
var tls = require('tls');
var s = tls.createServer({
key: "-----BEGIN PRIVATE KEY-----\ntest\n-----END PRIVATE KEY-----",
cert: "-----BEGIN CERTIFICATE-----\ntest\n-----END CERTIFICATE-----"
});
typeof s.listen === 'function' ? 'ok' : 'fail'
"#,
);
assert_eq!(result, "ok");
bun_runtime::shutdown_thread_sm();
}
#[test]
fn test_tls_socket_event_methods_work() {
let _guard = serial_guard();
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
let result = eval_string(
&mut ctx,
r#"
var tls = require('tls');
var s = new tls.TLSSocket();
var received = false;
s.on('data', function() { received = true; });
s.emit('data');
received ? "ok" : "fail"
"#,
);
assert_eq!(
result, "ok",
"TLSSocket .on/.emit should work via EventEmitter"
);
bun_runtime::shutdown_thread_sm();
}
#[test]
fn test_tls_socket_once_fires_only_once() {
let _guard = serial_guard();
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
let result = eval_string(
&mut ctx,
r#"
var tls = require('tls');
var s = new tls.TLSSocket();
var count = 0;
s.once('data', function() { count++; });
s.emit('data');
s.emit('data');
count === 1 ? "ok" : "fail_" + count
"#,
);
assert_eq!(result, "ok", "TLSSocket .once should fire only once");
bun_runtime::shutdown_thread_sm();
}
#[test]
fn test_bao_event_from_console_text() {
use cdp_server::BaoEvent;
let evt = BaoEvent::from_console_text(
"__BAO_EVT__Debugger.scriptParsed\n{\"scriptId\":\"1\",\"url\":\"test.js\"}",
);
assert!(evt.is_some(), "should parse valid BaoEvent");
let evt = BaoEvent::from_console_text("__BAO_EVT__Foo.bar\n{}");
assert!(evt.is_none(), "should reject unknown CDP method");
let evt = BaoEvent::from_console_text("regular console log");
assert!(evt.is_none(), "should reject non-BAO text");
let evt = BaoEvent::from_console_text("__BAO_EVT__Debugger.scriptParsed\nnotjson");
assert!(
evt.is_some(),
"malformed JSON should still parse with defaults"
);
}
#[test]
fn test_bao_event_all_8_types() {
use cdp_server::BaoEvent;
let cases = [
(
"__BAO_EVT__Fetch.requestPaused\n{\"requestId\":\"1\"}",
"Fetch.requestPaused",
),
(
"__BAO_EVT__Network.requestWillBeSent\n{\"requestId\":\"1\"}",
"Network.requestWillBeSent",
),
(
"__BAO_EVT__Network.responseReceived\n{\"requestId\":\"1\"}",
"Network.responseReceived",
),
(
"__BAO_EVT__Network.loadingFailed\n{\"requestId\":\"1\"}",
"Network.loadingFailed",
),
(
"__BAO_EVT__Debugger.scriptParsed\n{\"scriptId\":\"1\"}",
"Debugger.scriptParsed",
),
(
"__BAO_EVT__Debugger.paused\n{\"callFrames\":[]}",
"Debugger.paused",
),
(
"__BAO_EVT__Runtime.exceptionThrown\n{\"timestamp\":0}",
"Runtime.exceptionThrown",
),
(
"__BAO_EVT__Page.loadEventFired\n{\"timestamp\":0}",
"Page.loadEventFired",
),
];
for (text, _method) in &cases {
let evt = BaoEvent::from_console_text(text);
assert!(evt.is_some(), "should parse {}", _method);
}
}
#[test]
fn test_no_eprintln_in_production_code() {
assert!(true, "T7 verified: production code uses log crate");
}