#![cfg(feature = "childproc")]
use tower_mcp::transport::childproc::ChildProcessTransport;
#[tokio::test]
async fn response_correlates_by_id_past_a_leading_notification() {
let mut conn = ChildProcessTransport::new("sh")
.arg("-c")
.arg(concat!(
r#"read -r _line; "#,
r#"printf '{"jsonrpc":"2.0","method":"notifications/progress","params":{}}\n'; "#,
r#"printf '{"jsonrpc":"2.0","id":1,"result":{"ok":true}}\n'"#
))
.spawn()
.await
.unwrap();
let result = conn
.send_request("ping", serde_json::json!({}))
.await
.expect("the response after the notification must still be delivered");
assert_eq!(result, serde_json::json!({"ok": true}));
conn.shutdown().await.unwrap();
}
#[tokio::test]
async fn out_of_order_responses_are_matched_by_id_not_by_arrival_order() {
let mut conn = ChildProcessTransport::new("sh")
.arg("-c")
.arg(concat!(
r#"read -r _line; "#,
r#"printf '{"jsonrpc":"2.0","id":2,"result":{"which":2}}\n'; "#,
r#"printf '{"jsonrpc":"2.0","id":1,"result":{"which":1}}\n'; "#,
r#"cat >/dev/null"#
))
.spawn()
.await
.unwrap();
let first = conn
.send_request("a", serde_json::json!({}))
.await
.expect("id 1's own response must be returned, not id 2's");
assert_eq!(first, serde_json::json!({"which": 1}));
let second = conn
.send_request("b", serde_json::json!({}))
.await
.expect("the response set aside for id 2 must be delivered");
assert_eq!(second, serde_json::json!({"which": 2}));
conn.shutdown().await.unwrap();
}
#[tokio::test]
async fn invalid_utf8_frame_is_discarded_and_the_response_still_arrives() {
let mut conn = ChildProcessTransport::new("sh")
.arg("-c")
.arg(concat!(
r#"read -r _line; "#,
r#"printf '\377\376\n'; "#,
r#"printf '{"jsonrpc":"2.0","id":1,"result":{"ok":true}}\n'"#
))
.spawn()
.await
.unwrap();
let result = conn
.send_request("ping", serde_json::json!({}))
.await
.expect("a bad frame must cost only itself, not the connection");
assert_eq!(result, serde_json::json!({"ok": true}));
conn.shutdown().await.unwrap();
}
#[tokio::test]
async fn a_leading_bom_on_the_response_is_stripped() {
let mut conn = ChildProcessTransport::new("sh")
.arg("-c")
.arg(concat!(
r#"read -r _line; "#,
r#"printf '\357\273\277{"jsonrpc":"2.0","id":1,"result":{"ok":true}}\n'"#
))
.spawn()
.await
.unwrap();
let result = conn
.send_request("ping", serde_json::json!({}))
.await
.expect("a BOM-prefixed response must still parse");
assert_eq!(result, serde_json::json!({"ok": true}));
conn.shutdown().await.unwrap();
}