use bao_cdp::{handle_command, parse_message};
use serde_json::json;
const TID: &str = "perf-int-target";
fn msg(id: i64, method: &str) -> Option<bao_cdp::CdpMessage> {
let raw = format!(r#"{{"id":{},"method":"{}"}}"#, id, method);
parse_message(&raw)
}
#[test]
fn int_perf002_emulation_set_device_metrics_round_trip() {
let raw = r#"{"id":1,"method":"Emulation.setDeviceMetricsOverride","params":{"width":375,"height":812}}"#;
let parsed = parse_message(raw).expect("parse Emulation.setDeviceMetricsOverride");
let resp = handle_command(parsed, TID, &Some(json!({"width":375,"height":812})), None);
assert_eq!(resp.id, Some(1), "response id echoes request id");
assert!(
resp.result.is_some() || resp.error.is_some(),
"handler must terminate with either result or structured CdpError, never panic"
);
}
#[test]
fn int_perf002_emulation_clear_then_set_is_idempotent() {
for (i, method) in [
"Emulation.clearDeviceMetricsOverride",
"Emulation.setDeviceMetricsOverride",
"Emulation.clearDeviceMetricsOverride",
]
.iter()
.enumerate()
{
let parsed = msg(i as i64, method).expect("parse Emulation cycle");
let resp = handle_command(parsed, TID, &None, None);
assert_eq!(resp.id, Some(i as i64));
}
}
#[test]
fn int_perf002_network_enable_cycle_no_lock_poisoning() {
for i in 0..50i64 {
let parsed = msg(i, "Network.enable").expect("parse Network.enable");
let resp = handle_command(parsed, TID, &None, None);
assert_eq!(
resp.id,
Some(i),
"Network.enable iteration {i} must echo id"
);
}
}
#[test]
fn int_perf002_debugger_commands_are_single_threaded_safe() {
let cmds = ["Debugger.enable", "Debugger.disable", "Debugger.enable"];
for (i, m) in cmds.iter().enumerate() {
let parsed = msg(i as i64, m).expect("parse Debugger");
let _ = handle_command(parsed, TID, &None, None);
}
}
#[test]
fn int_perf003_response_serialization_is_deterministic() {
use bao_cdp::serialize_response;
let raw = r#"{"id":7,"method":"Page.navigate","params":{"url":"https://example.com"}}"#;
let parsed = parse_message(raw).expect("parse Page.navigate");
let resp = handle_command(
parsed,
TID,
&Some(json!({"url":"https://example.com"})),
None,
);
let s1 = serialize_response(&resp);
let s2 = serialize_response(&resp);
assert_eq!(
s1, s2,
"serialize_response must be deterministic (Bytes refcount, no mutation)"
);
}
#[test]
fn int_perf003_session_ids_are_unique_and_short() {
use bao_cdp::CdpRouter;
let router = CdpRouter::new();
let ids: Vec<String> = (0..20)
.map(|i| {
let tid = format!("target-{i}");
router
.create_internal_session(&tid)
.session_id()
.to_string()
})
.collect();
assert!(
ids.iter().all(|s| !s.is_empty() && s.len() <= 24),
"session IDs must be non-empty and short (CompactString inline range)"
);
let unique: std::collections::HashSet<_> = ids.iter().collect();
assert_eq!(unique.len(), 20, "20 sessions must produce 20 unique IDs");
}
#[test]
fn int_perf003_router_many_sessions_no_loss() {
use bao_cdp::{BackendKind, CdpRouter};
let router = CdpRouter::new();
for i in 0..100 {
let tid = format!("dash-target-{i}");
let s = router.create_internal_session(&tid);
assert_eq!(s.backend_kind(), BackendKind::Internal);
assert!(!s.session_id().is_empty());
}
}
#[test]
fn int_perf004_enum_dispatch_routes_all_known_domains() {
let probes: &[(&str, &str)] = &[
("Target", "getTargets"),
("Page", "enable"),
("Runtime", "enable"),
("DOM", "enable"),
("Network", "enable"),
("CSS", "enable"),
("Emulation", "setDeviceMetricsOverride"),
("Input", "dispatchMouseEvent"),
("Overlay", "enable"),
("Debugger", "enable"),
("Log", "enable"),
("Fetch", "enable"),
];
for (i, (domain, sub)) in probes.iter().enumerate() {
let method = format!("{}.{}", domain, sub);
let parsed = msg(i as i64, &method).expect("parse known domain probe");
let resp = handle_command(parsed, TID, &None, None);
if let Some(err) = &resp.error {
let routed_correctly =
!(err.code == -32601 && err.message.contains(&format!("'{}'", method)));
assert!(
routed_correctly,
"domain '{}' must reach its handler arm (got wildcard METHOD_NOT_FOUND: {})",
domain, err.message
);
}
}
}
#[test]
fn int_perf004_unknown_domain_returns_method_not_found() {
let parsed = msg(1, "BogusDomain.noop").expect("parse BogusDomain");
let resp = handle_command(parsed, TID, &None, None);
let err = resp.error.expect("unknown domain must produce error");
assert_eq!(err.code, -32601, "ERR_METHOD_NOT_FOUND for unknown domain");
}
#[test]
fn int_perf004_jsengine_singleton_is_once_lock_not_arc_mutex() {
use bao_engine::context::JsContext;
let mut ctx = match JsContext::for_test() {
Ok(c) => c,
Err(e) => {
eprintln!(
"SKIP int_perf004_jsengine_singleton: for_test unavailable: {:?}",
e
);
return;
}
};
let r1 = ctx.eval("6 * 7", "perf_test.js");
let r2 = ctx.eval("6 * 7", "perf_test.js");
assert!(
r1.is_ok(),
"first eval must succeed on OnceLock'd engine: {:?}",
r1.err()
);
assert!(
r2.is_ok(),
"second eval must succeed on the same OnceLock'd engine: {:?}",
r2.err()
);
JsContext::shutdown_test_runtime();
}
#[test]
fn int_perf005_empty_params_handled_without_box_new_array() {
let parsed = msg(1, "Page.reload").expect("parse Page.reload");
let resp = handle_command(parsed, TID, &None, None);
assert_eq!(resp.id, Some(1));
}
#[test]
fn int_perf005_target_list_returns_iterator_collected_array() {
let parsed = msg(1, "Target.getTargets").expect("parse Target.getTargets");
let resp = handle_command(parsed, TID, &None, None);
if let Some(result) = &resp.result {
if let Some(arr) = result.get("targetInfos").and_then(|v| v.as_array()) {
assert_eq!(
arr.iter().count(),
arr.len(),
"targetInfos must be iterator-collected (count == len)"
);
}
}
}
#[test]
fn int_perf005_repeated_commands_take_replace_buffers_intact() {
for i in 0..200i64 {
let parsed = msg(i, "Log.enable").expect("parse Log.enable");
let resp = handle_command(parsed, TID, &None, None);
assert_eq!(
resp.id,
Some(i),
"iteration {i} must round-trip correctly under take/replace"
);
}
}